1
1
/*
2
- * Copyright (c) 2012-2016 Todd C. Miller <Todd.Miller@courtesan.com>
2
+ * Copyright (c) 2012-2017 Todd C. Miller <Todd.Miller@courtesan.com>
3
3
*
4
4
* Permission to use, copy, modify, and distribute this software for any
5
5
* purpose with or without fee is hereby granted, provided that the above
@@ -145,37 +145,41 @@ sudo_ttyname_dev(dev_t tdev, char *name, size_t namelen)
145
145
}
146
146
#elif defined(HAVE_STRUCT_PSINFO_PR_TTYDEV ) || defined(HAVE_PSTAT_GETPROC ) || defined(__linux__ )
147
147
/*
148
- * Devices to search before doing a breadth-first scan.
148
+ * Device nodes and directories to search before searching all of /dev
149
149
*/
150
150
static char * search_devs [] = {
151
151
"/dev/console" ,
152
- "/dev/wscons" ,
153
- "/dev/pts /" ,
154
- "/dev/vt /" ,
155
- "/dev/term /" ,
156
- "/dev/zcons /" ,
152
+ "/dev/pts/" , /* POSIX pty */
153
+ "/dev/vt /" , /* Solaris virtual console */
154
+ "/dev/term /" , /* Solaris serial ports */
155
+ "/dev/zcons /" , /* Solaris zone console */
156
+ "/dev/pty /" , /* HP-UX old-style pty */
157
157
NULL
158
158
};
159
159
160
+ /*
161
+ * Device nodes to ignore when searching all of /dev
162
+ */
160
163
static char * ignore_devs [] = {
161
- "/dev/fd/" ,
162
164
"/dev/stdin" ,
163
165
"/dev/stdout" ,
164
166
"/dev/stderr" ,
165
167
NULL
166
168
};
167
169
168
170
/*
169
- * Do a breadth-first scan of dir looking for the specified device.
171
+ * Do a scan of a directory looking for the specified device.
172
+ * Does not descend into subdirectories.
170
173
* Returns name on success and NULL on failure, setting errno.
171
174
*/
172
175
static char *
173
- sudo_ttyname_scan (const char * dir , dev_t rdev , bool builtin , char * name , size_t namelen )
176
+ sudo_ttyname_scan (const char * dir , dev_t rdev , char * name , size_t namelen )
174
177
{
175
- size_t sdlen , num_subdirs = 0 , max_subdirs = 0 ;
176
- char pathbuf [PATH_MAX ], * * subdirs = NULL ;
178
+ size_t sdlen ;
179
+ char pathbuf [PATH_MAX ];
177
180
char * ret = NULL ;
178
181
struct dirent * dp ;
182
+ struct stat sb ;
179
183
unsigned int i ;
180
184
DIR * d = NULL ;
181
185
debug_decl (sudo_ttyname_scan , SUDO_DEBUG_UTIL )
@@ -187,6 +191,18 @@ sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin, char *name, size_t
187
191
if ((d = opendir (dir )) == NULL )
188
192
goto done ;
189
193
194
+ if (fstat (dirfd (d ), & sb ) == -1 ) {
195
+ sudo_debug_printf (SUDO_DEBUG_ERROR |SUDO_DEBUG_LINENO ,
196
+ "unable to fstat %s" , dir );
197
+ goto done ;
198
+ }
199
+ if ((sb .st_mode & S_IWOTH ) != 0 ) {
200
+ sudo_debug_printf (SUDO_DEBUG_ERROR |SUDO_DEBUG_LINENO ,
201
+ "ignoring world-writable directory %s" , dir );
202
+ errno = ENOENT ;
203
+ goto done ;
204
+ }
205
+
190
206
sudo_debug_printf (SUDO_DEBUG_INFO |SUDO_DEBUG_LINENO ,
191
207
"scanning for dev %u in %s" , (unsigned int )rdev , dir );
192
208
@@ -224,18 +240,6 @@ sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin, char *name, size_t
224
240
}
225
241
if (ignore_devs [i ] != NULL )
226
242
continue ;
227
- if (!builtin ) {
228
- /* Skip entries in search_devs; we already checked them. */
229
- for (i = 0 ; search_devs [i ] != NULL ; i ++ ) {
230
- len = strlen (search_devs [i ]);
231
- if (search_devs [i ][len - 1 ] == '/' )
232
- len -- ;
233
- if (d_len == len && strncmp (pathbuf , search_devs [i ], len ) == 0 )
234
- break ;
235
- }
236
- if (search_devs [i ] != NULL )
237
- continue ;
238
- }
239
243
# if defined(HAVE_STRUCT_DIRENT_D_TYPE ) && defined(DTTOIF )
240
244
/*
241
245
* Avoid excessive stat() calls by checking dp->d_type.
@@ -248,39 +252,14 @@ sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin, char *name, size_t
248
252
if (stat (pathbuf , & sb ) == -1 )
249
253
continue ;
250
254
break ;
251
- case DT_DIR :
252
- /* Directory, no need to stat() it. */
253
- sb .st_mode = DTTOIF (dp -> d_type );
254
- sb .st_rdev = 0 ; /* quiet ccc-analyzer false positive */
255
- break ;
256
255
default :
257
- /* Not a character device, link or directory , skip it. */
256
+ /* Not a character device or link , skip it. */
258
257
continue ;
259
258
}
260
259
# else
261
260
if (stat (pathbuf , & sb ) == -1 )
262
261
continue ;
263
262
# endif
264
- if (S_ISDIR (sb .st_mode )) {
265
- if (!builtin ) {
266
- /* Add to list of subdirs to search. */
267
- if (num_subdirs + 1 > max_subdirs ) {
268
- char * * new_subdirs ;
269
-
270
- new_subdirs = reallocarray (subdirs , max_subdirs + 64 ,
271
- sizeof (char * ));
272
- if (new_subdirs == NULL )
273
- goto done ;
274
- subdirs = new_subdirs ;
275
- max_subdirs += 64 ;
276
- }
277
- subdirs [num_subdirs ] = strdup (pathbuf );
278
- if (subdirs [num_subdirs ] == NULL )
279
- goto done ;
280
- num_subdirs ++ ;
281
- }
282
- continue ;
283
- }
284
263
if (S_ISCHR (sb .st_mode ) && sb .st_rdev == rdev ) {
285
264
sudo_debug_printf (SUDO_DEBUG_INFO |SUDO_DEBUG_LINENO ,
286
265
"resolved dev %u as %s" , (unsigned int )rdev , pathbuf );
@@ -296,16 +275,9 @@ sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin, char *name, size_t
296
275
}
297
276
}
298
277
299
- /* Search subdirs if we didn't find it in the root level. */
300
- for (i = 0 ; ret == NULL && i < num_subdirs ; i ++ )
301
- ret = sudo_ttyname_scan (subdirs [i ], rdev , false, name , namelen );
302
-
303
278
done :
304
279
if (d != NULL )
305
280
closedir (d );
306
- for (i = 0 ; i < num_subdirs ; i ++ )
307
- free (subdirs [i ]);
308
- free (subdirs );
309
281
debug_return_str (ret );
310
282
}
311
283
@@ -324,7 +296,7 @@ sudo_ttyname_dev(dev_t rdev, char *name, size_t namelen)
324
296
debug_decl (sudo_ttyname_dev , SUDO_DEBUG_UTIL )
325
297
326
298
/*
327
- * First check search_devs for common tty devices.
299
+ * First check search_devs[] for common tty devices.
328
300
*/
329
301
for (sd = search_devs ; (devname = * sd ) != NULL ; sd ++ ) {
330
302
len = strlen (devname );
@@ -349,7 +321,7 @@ sudo_ttyname_dev(dev_t rdev, char *name, size_t namelen)
349
321
"comparing dev %u to %s: no" , (unsigned int )rdev , buf );
350
322
} else {
351
323
/* Traverse directory */
352
- ret = sudo_ttyname_scan (devname , rdev , true, name , namelen );
324
+ ret = sudo_ttyname_scan (devname , rdev , name , namelen );
353
325
if (ret != NULL || errno == ENOMEM )
354
326
goto done ;
355
327
}
@@ -367,9 +339,9 @@ sudo_ttyname_dev(dev_t rdev, char *name, size_t namelen)
367
339
}
368
340
369
341
/*
370
- * Not found? Do a breadth-first traversal of /dev/ .
342
+ * Not found? Check all device nodes in /dev.
371
343
*/
372
- ret = sudo_ttyname_scan (_PATH_DEV , rdev , false, name , namelen );
344
+ ret = sudo_ttyname_scan (_PATH_DEV , rdev , name , namelen );
373
345
374
346
done :
375
347
debug_return_str (ret );
@@ -493,28 +465,35 @@ get_process_ttyname(char *name, size_t namelen)
493
465
len = getline (& line , & linesize , fp );
494
466
fclose (fp );
495
467
if (len != -1 ) {
496
- /* Field 7 is the tty dev (0 if no tty) */
497
- char * cp = line ;
498
- char * ep = line ;
499
- const char * errstr ;
500
- int field = 0 ;
501
- while (* ++ ep != '\0' ) {
502
- if (* ep == ' ' ) {
503
- * ep = '\0' ;
504
- if (++ field == 7 ) {
505
- dev_t tdev = strtonum (cp , INT_MIN , INT_MAX , & errstr );
506
- if (errstr ) {
507
- sudo_debug_printf (SUDO_DEBUG_ERROR |SUDO_DEBUG_LINENO ,
508
- "%s: tty device %s: %s" , path , cp , errstr );
509
- }
510
- if (tdev > 0 ) {
511
- errno = serrno ;
512
- ret = sudo_ttyname_dev (tdev , name , namelen );
513
- goto done ;
468
+ /*
469
+ * Field 7 is the tty dev (0 if no tty).
470
+ * Since the process name at field 2 "(comm)" may include spaces,
471
+ * start at the last ')' found.
472
+ */
473
+ char * cp = strrchr (line , ')' );
474
+ if (cp != NULL ) {
475
+ char * ep = cp ;
476
+ const char * errstr ;
477
+ int field = 1 ;
478
+
479
+ while (* ++ ep != '\0' ) {
480
+ if (* ep == ' ' ) {
481
+ * ep = '\0' ;
482
+ if (++ field == 7 ) {
483
+ dev_t tdev = strtonum (cp , INT_MIN , INT_MAX , & errstr );
484
+ if (errstr ) {
485
+ sudo_debug_printf (SUDO_DEBUG_ERROR |SUDO_DEBUG_LINENO ,
486
+ "%s: tty device %s: %s" , path , cp , errstr );
487
+ }
488
+ if (tdev > 0 ) {
489
+ errno = serrno ;
490
+ ret = sudo_ttyname_dev (tdev , name , namelen );
491
+ goto done ;
492
+ }
493
+ break ;
514
494
}
515
- break ;
495
+ cp = ep + 1 ;
516
496
}
517
- cp = ep + 1 ;
518
497
}
519
498
}
520
499
}
0 commit comments