@@ -212,7 +212,9 @@ static int execute_qrexec_service(
212
212
213
213
/*
214
214
Find a file in the ':'-delimited list of paths given in path_list.
215
- Returns 0 on success, -1 on failure.
215
+ Returns 0 on success, -1 if the file is definitely absent in all of the
216
+ paths, and -2 on error (broken symlink, I/O error, path too long, out
217
+ of memory, etc).
216
218
On success, fills buffer and statbuf (unless statbuf is NULL).
217
219
*/
218
220
static int find_file (
@@ -225,6 +227,10 @@ static int find_file(
225
227
struct stat dummy_buf ;
226
228
const char * path_start = path_list ;
227
229
size_t name_length = strlen (name );
230
+ int res ;
231
+
232
+ if (name_length > NAME_MAX )
233
+ return -1 ; /* cannot possibly exist */
228
234
229
235
if (!statbuf )
230
236
statbuf = & dummy_buf ;
@@ -236,15 +242,27 @@ static int find_file(
236
242
237
243
if (path_length + name_length + 1 >= buffer_size ) {
238
244
LOG (ERROR , "find_qrexec_service_file: buffer too small for file path" );
239
- return -1 ;
245
+ return -2 ;
240
246
}
241
247
242
248
memcpy (buffer , path_start , path_length );
243
249
buffer [path_length ] = '/' ;
244
250
strcpy (buffer + path_length + 1 , name );
245
251
//LOG(INFO, "stat(%s)", buffer);
246
- if (stat (buffer , statbuf ) == 0 )
252
+ res = lstat (buffer , statbuf );
253
+ if (res == 0 && S_ISLNK (statbuf -> st_mode )) {
254
+ /* check if the symlink is valid */
255
+ res = stat (buffer , statbuf );
256
+ assert (res == -1 || !S_ISLNK (statbuf -> st_mode ));
257
+ }
258
+ if (res == 0 ) {
247
259
return 0 ;
260
+ } else {
261
+ assert (res == -1 );
262
+ if (errno != ENOENT ) {
263
+ return -2 ;
264
+ }
265
+ }
248
266
249
267
path_start = path_end ;
250
268
while (* path_start == ':' )
@@ -264,7 +282,7 @@ static int load_service_config_raw(struct qrexec_parsed_command *cmd,
264
282
265
283
int ret = find_file (config_path , cmd -> service_descriptor ,
266
284
config_full_path , sizeof (config_full_path ), NULL );
267
- if (ret < 0 && strcmp (cmd -> service_descriptor , cmd -> service_name ) != 0 )
285
+ if (ret == -1 && strcmp (cmd -> service_descriptor , cmd -> service_name ) != 0 )
268
286
ret = find_file (config_path , cmd -> service_name ,
269
287
config_full_path , sizeof (config_full_path ), NULL );
270
288
if (ret < 0 )
@@ -462,7 +480,7 @@ static int execute_qrexec_service(
462
480
int ret = find_file (qrexec_service_path , cmd -> service_descriptor ,
463
481
service_full_path , sizeof (service_full_path ),
464
482
& statbuf );
465
- if (ret < 0 && strcmp (cmd -> service_descriptor , cmd -> service_name ) != 0 )
483
+ if (ret == -1 && strcmp (cmd -> service_descriptor , cmd -> service_name ) != 0 )
466
484
ret = find_file (qrexec_service_path , cmd -> service_name ,
467
485
service_full_path , sizeof (service_full_path ),
468
486
& statbuf );
0 commit comments