From 4f0b540d08f5912b273c427218cc665512b12de5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 6 Apr 2017 15:22:24 +0200 Subject: modprobe: do not descend into /etc/modprobe.d/DIR/. Closes 8686 Also expanded comments in recursive_action.c Signed-off-by: Denys Vlasenko --- libbb/recursive_action.c | 46 +++++++++++++++++++++++++++++----------------- modutils/modprobe.c | 9 +++++++++ 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/libbb/recursive_action.c b/libbb/recursive_action.c index b5cf7c0ab..8f2b8b932 100644 --- a/libbb/recursive_action.c +++ b/libbb/recursive_action.c @@ -30,24 +30,37 @@ static int FAST_FUNC true_action(const char *fileName UNUSED_PARAM, return TRUE; } -/* fileAction return value of 0 on any file in directory will make - * recursive_action() return 0, but it doesn't stop directory traversal +/* fileName is (l)stat'ed (depending on ACTION_FOLLOWLINKS[_L0]). + * + * If it is a file: fileAction in run on it, its return value is returned. + * + * In case we are in a recursive invocation (see below): + * normally, fileAction should return 1 (TRUE) to indicate that + * everything is okay and processing should continue. + * fileAction return value of 0 (FALSE) on any file in directory will make + * recursive_action() also return 0, but it doesn't stop directory traversal * (fileAction/dirAction will be called on each file). * - * If !ACTION_RECURSE, dirAction is called on the directory and its + * [TODO: maybe introduce -1 to mean "stop traversal NOW and return"] + * + * If it is a directory: + * + * If !ACTION_RECURSE, dirAction is called and its * return value is returned from recursive_action(). No recursion. * - * If ACTION_RECURSE, recursive_action() is called on each directory. + * If ACTION_RECURSE, directory is opened, and recursive_action() is called + * on each file/subdirectory. * If any one of these calls returns 0, current recursive_action() returns 0. * + * If !ACTION_DEPTHFIRST, dirAction is called before recurse. + * Return value of 0 (FALSE) is an error: prevents recursion, + * the warning is printed (unless ACTION_QUIET) and recursive_action() returns 0. + * Return value of 2 (SKIP) prevents recursion, instead recursive_action() + * returns 1 (TRUE, no error). + * * If ACTION_DEPTHFIRST, dirAction is called after recurse. * If it returns 0, the warning is printed and recursive_action() returns 0. * - * If !ACTION_DEPTHFIRST, dirAction is called before we recurse. - * Return value of 0 (FALSE) or 2 (SKIP) prevents recursion - * into that directory, instead recursive_action() returns 0 (if FALSE) - * or 1 (if SKIP) - * * ACTION_FOLLOWLINKS mainly controls handling of links to dirs. * 0: lstat(statbuf). Calls fileAction on link name even if points to dir. * 1: stat(statbuf). Calls dirAction and optionally recurse on link to dir. @@ -105,7 +118,7 @@ int FAST_FUNC recursive_action(const char *fileName, if (!(flags & ACTION_DEPTHFIRST)) { status = dirAction(fileName, &statbuf, userData, depth); - if (!status) + if (status == FALSE) goto done_nak_warn; if (status == SKIP) return TRUE; @@ -121,24 +134,23 @@ int FAST_FUNC recursive_action(const char *fileName, status = TRUE; while ((next = readdir(dir)) != NULL) { char *nextFile; + int s; nextFile = concat_subpath_file(fileName, next->d_name); if (nextFile == NULL) continue; + /* process every file (NB: ACTION_RECURSE is set in flags) */ - if (!recursive_action(nextFile, flags, fileAction, dirAction, - userData, depth + 1)) + s = recursive_action(nextFile, flags, fileAction, dirAction, + userData, depth + 1); + if (s == FALSE) status = FALSE; -// s = recursive_action(nextFile, flags, fileAction, dirAction, -// userData, depth + 1); free(nextFile); -//#define RECURSE_RESULT_ABORT 3 +//#define RECURSE_RESULT_ABORT -1 // if (s == RECURSE_RESULT_ABORT) { // closedir(dir); // return s; // } -// if (s == FALSE) -// status = FALSE; } closedir(dir); diff --git a/modutils/modprobe.c b/modutils/modprobe.c index c82eaa8d8..51ede9204 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c @@ -252,6 +252,15 @@ static int FAST_FUNC config_file_action(const char *filename, if (base[0] == '.') goto error; + /* "man modprobe.d" from kmod version 22 suggests + * that we shouldn't recurse into /etc/modprobe.d/dir/ + * _subdirectories_: + */ + if (depth > 1) + return SKIP; /* stop recursing */ +//TODO: instead, can use dirAction in recursive_action() to SKIP dirs +//on depth == 1 level. But that's more code... + /* In dir recursion, skip files that do not end with a ".conf" * depth==0: read_config("modules.{symbols,alias}") must work, * "include FILE_NOT_ENDING_IN_CONF" must work too. -- cgit v1.2.3