12 #include "trinity.h" // __unused__
13 #include "arch.h" // page_size
14 #include "constants.h"
26 static int files_added
= 0;
27 const char **fileindex
;
28 unsigned int files_in_index
= 0;
29 unsigned int nr_file_fds
= 0;
32 struct list_head list
;
36 static struct namelist
*names
= NULL
;
38 static int ignore_files(const char *path
)
41 unsigned int pathlen
, offset
= 0;
43 /* These are exact matches. */
44 const char *ignored_paths
[] = {
47 /* dangerous/noisy/annoying stuff in /proc */
48 "/proc/sysrq-trigger", "/proc/kmem", "/proc/kcore",
50 /* dangerous/noisy/annoying stuff in /dev */
51 "/dev/log", "/dev/mem", "/dev/kmsg",
55 /* Partial matches. */ //FIXME: This whole function should just use globs to pattern match.
56 const char *ignored_patterns
[] = {
58 /* dangerous/noisy/annoying per-process stuff. */
59 "coredump_filter", "make-it-fail", "oom_adj", "oom_score_adj",
63 pathlen
= strlen(path
);
65 /* First do the exact matches */
66 for (i
= 0; ignored_paths
[i
]; i
++) {
67 if (strlen(ignored_paths
[i
]) != pathlen
) {
71 if (!strcmp(path
, ignored_paths
[i
])) {
72 debugf("Skipping %s\n", path
);
77 /* Now make sure none of the patterns match the end of the pathname */
78 for (j
= 0; j
< pathlen
; j
++) {
87 for (i
= 0; ignored_patterns
[i
]; i
++) {
88 if (!strcmp(path
+ offset
, ignored_patterns
[i
])) {
89 debugf("Skipping pattern %s\n", path
);
94 /* special case to match tty* until I do globbing */
95 if (!strncmp(path
+ offset
, "tty", 3)) {
96 debugf("Skipping %s\n", path
);
102 static void add_to_namelist(const char *name
)
104 struct namelist
*newnode
;
105 struct list_head
*list
= (struct list_head
*) names
;
107 newnode
= zmalloc(sizeof(struct namelist
));
108 newnode
->name
= strdup(name
);
109 list_add_tail(&newnode
->list
, list
);
112 static int check_stat_file(const struct stat
*sb
)
115 bool set_read
= FALSE
;
116 bool set_write
= FALSE
;
117 uid_t target_uid
= orig_uid
;
118 gid_t target_gid
= orig_gid
;
120 if (dropprivs
== TRUE
) {
121 target_uid
= nobody_uid
;
122 target_gid
= nobody_gid
;
125 if (S_ISLNK(sb
->st_mode
))
128 if (sb
->st_uid
== target_uid
) {
129 if (sb
->st_mode
& S_IRUSR
)
131 if (sb
->st_mode
& S_IWUSR
)
135 if (sb
->st_gid
== target_gid
) {
136 if (sb
->st_mode
& S_IRGRP
)
138 if (sb
->st_mode
& S_IWGRP
)
142 if (sb
->st_mode
& S_IROTH
)
144 if (sb
->st_mode
& S_IWOTH
)
148 if ((set_read
| set_write
) == 0)
151 if (set_read
== TRUE
)
153 if (set_write
== TRUE
)
155 if ((set_read
== TRUE
) && (set_write
== TRUE
))
158 if (S_ISDIR(sb
->st_mode
))
164 static int file_tree_callback(const char *fpath
, const struct stat
*sb
, __unused__
int typeflag
, __unused__
struct FTW
*ftwbuf
)
167 if (ignore_files(fpath
)) {
168 return FTW_SKIP_SUBTREE
;
171 // Check we can read it.
172 if (check_stat_file(sb
) == -1)
175 if (shm
->exit_reason
!= STILL_RUNNING
)
178 add_to_namelist(fpath
);
185 static void open_fds(const char *dirpath
)
187 int before
= files_added
;
188 int flags
= FTW_DEPTH
| FTW_ACTIONRETVAL
| FTW_MOUNT
;
191 /* By default, don't follow symlinks so we only get each file once.
192 * But, if we do something like -V /lib, then follow it
194 * I'm not sure about this, might remove later.
196 if (victim_path
== NULL
)
199 ret
= nftw(dirpath
, file_tree_callback
, 32, flags
);
201 if (shm
->exit_reason
!= EXIT_SIGINT
)
202 output(0, "Something went wrong during nftw(%s). (%d:%s)\n",
203 dirpath
, ret
, strerror(errno
));
207 output(0, "Added %d filenames from %s\n", files_added
- before
, dirpath
);
210 static void generate_filelist(void)
213 struct list_head
*node
;
216 names
= zmalloc(sizeof(struct namelist
));
217 INIT_LIST_HEAD(&names
->list
);
219 output(1, "Generating file descriptors\n");
221 if (victim_path
!= NULL
) {
222 open_fds(victim_path
);
229 if (shm
->exit_reason
!= STILL_RUNNING
)
232 if (files_added
== 0) {
233 output(1, "Didn't add any files!!\n");
237 /* Generate an index of pointers to the filenames */
239 fileindex
= malloc(sizeof(char *) * files_added
);
241 list_for_each(node
, &names
->list
) {
242 nl
= (struct namelist
*) node
;
243 fileindex
[i
++] = nl
->name
;
248 static int open_file(void)
253 const char *filename
;
254 int flags
, randflags
;
259 filename
= get_filename();
260 ret
= lstat(filename
, &sb
);
264 flags
= check_stat_file(&sb
);
268 /* OR in some random flags. */
270 randflags
= get_o_flags();
272 fd
= open(filename
, flags
| randflags
| O_NONBLOCK
);
275 * if we failed to open the file, retry with different flags.
276 * we should eventually succeed, but set an arbitary upper limit of
277 * 50 tries before just giving up.
281 output(2, "Couldn't open %s : %s\n", filename
, strerror(errno
));
288 case O_RDONLY
: modestr
= "read-only"; break;
289 case O_WRONLY
: modestr
= "write-only"; break;
290 case O_RDWR
: modestr
= "read-write"; break;
291 default: modestr
= "unknown"; break;
293 output(2, "fd[%i] = %s (%s) flags:%x\n", fd
, filename
, modestr
, randflags
);
299 unsigned int i
, nr_to_open
;
303 if (files_in_index
== 0) /* Something bad happened. Crappy -V maybe? */
304 return FALSE
; // FIXME: We should log something here probably.
306 if (files_in_index
< NR_FILE_FDS
)
307 nr_to_open
= files_in_index
;
309 nr_to_open
= NR_FILE_FDS
;
311 if (fileindex
== NULL
) /* this can happen if we ctrl-c'd */
314 for (i
= 0; i
< nr_to_open
; i
++) {
319 shm
->file_fds
[i
] = fd
;
325 void close_files(void)
330 shm
->fd_lifetime
= 0;
332 // FIXME: Does this need locking? At the least, check for NULL fd's
333 for (i
= 0; i
< nr_file_fds
; i
++) {
336 fd
= shm
->file_fds
[i
];
337 shm
->file_fds
[i
] = 0;
345 const char * get_filename(void)
347 if (files_in_index
== 0) /* This can happen if we run with -n. Should we do something else ? */
350 return fileindex
[rand() % files_in_index
];
353 int rand_file_fd(void)
355 unsigned int fd_index
;
357 fd_index
= rand() % nr_file_fds
;
358 return shm
->file_fds
[fd_index
];