2
2
3
3
#include <dirent.h>
4
4
#include <errno.h>
5
+ #include <fcntl.h>
5
6
#include <stdio.h>
6
7
#include <stdlib.h>
7
8
#include <string.h>
15
16
#include "shadowlog_internal.h"
16
17
17
18
18
- static int run_part (char * script_path , const char * name , const char * action )
19
+ static int run_part (int script_fd , const char * script_name , const char * name , const char * action )
19
20
{
20
21
pid_t pid ;
21
22
int wait_status ;
22
23
pid_t pid_status ;
23
- char * args [] = { script_path , NULL };
24
+ char * args [] = { ( char * ) script_name , NULL };
24
25
25
26
pid = fork ();
26
27
if (pid == -1 ) {
@@ -30,8 +31,8 @@ static int run_part(char *script_path, const char *name, const char *action)
30
31
if (pid == 0 ) {
31
32
setenv ("ACTION" ,action ,1 );
32
33
setenv ("SUBJECT" ,name ,1 );
33
- execv ( script_path , args );
34
- fprintf (shadow_logfd , "execv : %s\n" , strerror (errno ));
34
+ fexecve ( script_fd , args , environ );
35
+ fprintf (shadow_logfd , "fexecve(%s) : %s\n" , script_name , strerror (errno ));
35
36
exit (1 );
36
37
}
37
38
@@ -40,7 +41,7 @@ static int run_part(char *script_path, const char *name, const char *action)
40
41
return (wait_status );
41
42
}
42
43
43
- fprintf (shadow_logfd , "waitpid : %s\n" , strerror (errno ));
44
+ fprintf (shadow_logfd , "failed to wait for pid %d (%s) : %s\n" , pid , script_name , strerror (errno ));
44
45
return (1 );
45
46
}
46
47
@@ -51,68 +52,82 @@ int run_parts(const char *directory, const char *name, const char *action)
51
52
int n ;
52
53
int execute_result = 0 ;
53
54
55
+ int dfd = open (directory , O_PATH | O_DIRECTORY | O_CLOEXEC );
56
+ if (dfd == -1 ) {
57
+ fprintf (shadow_logfd , "failed open directory %s: %s\n" , directory , strerror (errno ));
58
+ return (1 );
59
+ }
60
+
61
+ #ifdef HAVE_SCANDIRAT
62
+ scanlist = scandirat (dfd , "." , & namelist , 0 , alphasort );
63
+ #else
54
64
scanlist = scandir (directory , & namelist , 0 , alphasort );
65
+ #endif
55
66
if (scanlist <=0 ) {
67
+ (void ) close (dfd );
56
68
return (0 );
57
69
}
58
70
59
71
for (n = 0 ; n < scanlist ; n ++ ) {
60
- char * s ;
61
- struct stat sb ;
62
-
63
- if (asprintf (& s , "%s/%s" , directory , namelist [n ]-> d_name ) == -1 ) {
64
- fprintf (shadow_logfd , "asprintf: %s\n" , strerror (errno ));
65
- for (; n < scanlist ; n ++ ) {
66
- free (namelist [n ]);
72
+ struct stat sb ;
73
+
74
+ int fd = openat (dfd , namelist [n ]-> d_name , O_PATH | O_CLOEXEC );
75
+ if (fd == -1 ) {
76
+ fprintf (shadow_logfd , "failed to open %s/%s: %s\n" ,
77
+ directory , namelist [n ]-> d_name , strerror (errno ));
78
+ for (int k = n ; k < scanlist ; k ++ ) {
79
+ free (namelist [k ]);
67
80
}
68
81
free (namelist );
82
+ (void ) close (dfd );
69
83
return (1 );
70
84
}
71
85
72
- execute_result = 0 ;
73
- if (stat (s , & sb ) == -1 ) {
74
- fprintf (shadow_logfd , "stat: %s\n" , strerror (errno ));
75
- free (s );
76
- for (; n < scanlist ; n ++ ) {
77
- free (namelist [n ]);
86
+ if (fstat (fd , & sb ) == -1 ) {
87
+ fprintf (shadow_logfd , "failed to stat %s/%s: %s\n" ,
88
+ directory , namelist [n ]-> d_name , strerror (errno ));
89
+ (void ) close (fd );
90
+ (void ) close (dfd );
91
+ for (int k = n ; k < scanlist ; k ++ ) {
92
+ free (namelist [k ]);
78
93
}
79
94
free (namelist );
80
95
return (1 );
81
96
}
82
97
83
98
if (!S_ISREG (sb .st_mode )) {
84
- free ( s );
99
+ ( void ) close ( fd );
85
100
free (namelist [n ]);
86
101
continue ;
87
102
}
88
103
89
104
if ((sb .st_uid != 0 && sb .st_uid != getuid ()) ||
90
105
(sb .st_gid != 0 && sb .st_gid != getgid ()) ||
91
106
(sb .st_mode & 0002 )) {
92
- fprintf (shadow_logfd , "skipping %s due to insecure ownership/permission\n" ,
93
- s );
94
- free ( s );
107
+ fprintf (shadow_logfd , "skipping %s/%s due to insecure ownership/permission\n" ,
108
+ directory , namelist [ n ] -> d_name );
109
+ ( void ) close ( fd );
95
110
free (namelist [n ]);
96
111
continue ;
97
112
}
98
113
99
- execute_result = run_part (s , name , action );
114
+ execute_result = run_part (fd , namelist [n ]-> d_name , name , action );
115
+ (void ) close (fd );
100
116
if (execute_result != 0 ) {
101
117
fprintf (shadow_logfd ,
102
- "%s: did not exit cleanly.\n" ,
103
- s );
104
- free (s );
105
- for (; n < scanlist ; n ++ ) {
106
- free (namelist [n ]);
118
+ "%s/%s: did not exit cleanly.\n" ,
119
+ directory , namelist [n ]-> d_name );
120
+ for (int k = n ; k < scanlist ; k ++ ) {
121
+ free (namelist [k ]);
107
122
}
108
123
break ;
109
124
}
110
125
111
- free (s );
112
126
free (namelist [n ]);
113
127
}
114
128
free (namelist );
115
129
130
+ (void ) close (dfd );
131
+
116
132
return (execute_result );
117
133
}
118
-
0 commit comments