mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 08:24:42 +01:00
parser: Fix parser failing to handle errors when setting up work
The parser is not correctly handling some error conditions when dealing with work units. Failure to spawn work, access files, etc should be returned where appropriate, and be able to abort processing if abort_on_error is set. In addition some errors are leading to a direct exit without checking for abort_on_error. BugLink: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=921866 BugLink: http://bugs.launchpad.net/bugs/1815294 Signed-off-by: John Johansen <john.johansen@canonical.com> Acked-by: Eric Chiang <ericchiang@google.com>
This commit is contained in:
parent
5e5b02b722
commit
1259319508
2 changed files with 54 additions and 17 deletions
|
@ -171,13 +171,23 @@ extern int preprocess_only;
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define PDEBUG(fmt, args...) fprintf(stderr, "parser: " fmt, ## args)
|
#define PDEBUG(fmt, args...) \
|
||||||
|
do { \
|
||||||
|
int pdebug_error = errno; \
|
||||||
|
fprintf(stderr, "parser: " fmt, ## args); \
|
||||||
|
errno = pdebug_error; \
|
||||||
|
} while (0)
|
||||||
#else
|
#else
|
||||||
#define PDEBUG(fmt, args...) /* Do nothing */
|
#define PDEBUG(fmt, args...) /* Do nothing */
|
||||||
#endif
|
#endif
|
||||||
#define NPDEBUG(fmt, args...) /* Do nothing */
|
#define NPDEBUG(fmt, args...) /* Do nothing */
|
||||||
|
|
||||||
#define PERROR(fmt, args...) fprintf(stderr, fmt, ## args)
|
#define PERROR(fmt, args...) \
|
||||||
|
do { \
|
||||||
|
int perror_error = errno; \
|
||||||
|
fprintf(stderr, fmt, ## args); \
|
||||||
|
errno = perror_error; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#ifndef TRUE
|
#ifndef TRUE
|
||||||
#define TRUE (1)
|
#define TRUE (1)
|
||||||
|
|
|
@ -1090,8 +1090,11 @@ do { \
|
||||||
work_sync_one(RESULT); \
|
work_sync_one(RESULT); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/* returns -1 if work_spawn fails, not a return value of any unit of work */
|
||||||
#define work_spawn(WORK, RESULT) \
|
#define work_spawn(WORK, RESULT) \
|
||||||
do { \
|
({ \
|
||||||
|
int localrc = 0; \
|
||||||
|
do { \
|
||||||
if (jobs == 0) { \
|
if (jobs == 0) { \
|
||||||
/* no parallel work so avoid fork() overhead */ \
|
/* no parallel work so avoid fork() overhead */ \
|
||||||
RESULT(WORK); \
|
RESULT(WORK); \
|
||||||
|
@ -1127,11 +1130,17 @@ do { \
|
||||||
fprintf(stderr, " JOBS SPAWN: created %ld ...\n", njobs); \
|
fprintf(stderr, " JOBS SPAWN: created %ld ...\n", njobs); \
|
||||||
} else { \
|
} else { \
|
||||||
/* error */ \
|
/* error */ \
|
||||||
if (debug_jobs) \
|
if (debug_jobs) { \
|
||||||
fprintf(stderr, " JOBS SPAWN: failed error: %d) ...\n", errno); \
|
int error = errno; \
|
||||||
|
fprintf(stderr, " JOBS SPAWN: failed error: %d) ...\n", errno); \
|
||||||
|
errno = error; \
|
||||||
|
} \
|
||||||
RESULT(errno); \
|
RESULT(errno); \
|
||||||
|
localrc = -1; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0); \
|
||||||
|
localrc; \
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
/* sadly C forces us to do this with exit, long_jump or returning error
|
/* sadly C forces us to do this with exit, long_jump or returning error
|
||||||
|
@ -1208,11 +1217,15 @@ static int profile_dir_cb(int dirfd unused, const char *name, struct stat *st,
|
||||||
if (!S_ISDIR(st->st_mode) && !is_blacklisted(name, NULL)) {
|
if (!S_ISDIR(st->st_mode) && !is_blacklisted(name, NULL)) {
|
||||||
struct dir_cb_data *cb_data = (struct dir_cb_data *)data;
|
struct dir_cb_data *cb_data = (struct dir_cb_data *)data;
|
||||||
autofree char *path = NULL;
|
autofree char *path = NULL;
|
||||||
if (asprintf(&path, "%s/%s", cb_data->dirname, name) < 0)
|
if (asprintf(&path, "%s/%s", cb_data->dirname, name) < 0) {
|
||||||
PERROR(_("Out of memory"));
|
PERROR(_("Out of memory"));
|
||||||
work_spawn(process_profile(option, cb_data->kernel_interface,
|
handle_work_result(errno);
|
||||||
path, cb_data->policy_cache),
|
return -1;
|
||||||
handle_work_result);
|
}
|
||||||
|
rc = work_spawn(process_profile(option,
|
||||||
|
cb_data->kernel_interface,
|
||||||
|
path, cb_data->policy_cache),
|
||||||
|
handle_work_result);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -1226,11 +1239,15 @@ static int binary_dir_cb(int dirfd unused, const char *name, struct stat *st,
|
||||||
if (!S_ISDIR(st->st_mode) && !is_blacklisted(name, NULL)) {
|
if (!S_ISDIR(st->st_mode) && !is_blacklisted(name, NULL)) {
|
||||||
struct dir_cb_data *cb_data = (struct dir_cb_data *)data;
|
struct dir_cb_data *cb_data = (struct dir_cb_data *)data;
|
||||||
autofree char *path = NULL;
|
autofree char *path = NULL;
|
||||||
if (asprintf(&path, "%s/%s", cb_data->dirname, name) < 0)
|
if (asprintf(&path, "%s/%s", cb_data->dirname, name) < 0) {
|
||||||
PERROR(_("Out of memory"));
|
PERROR(_("Out of memory"));
|
||||||
work_spawn(process_binary(option, cb_data->kernel_interface,
|
handle_work_result(errno);
|
||||||
path),
|
return -1;
|
||||||
handle_work_result);
|
}
|
||||||
|
rc = work_spawn(process_binary(option,
|
||||||
|
cb_data->kernel_interface,
|
||||||
|
path),
|
||||||
|
handle_work_result);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -1360,11 +1377,14 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
/* skip stdin if we've seen other command line arguments */
|
/* skip stdin if we've seen other command line arguments */
|
||||||
if (i == argc && optind != argc)
|
if (i == argc && optind != argc)
|
||||||
continue;
|
goto cleanup;
|
||||||
|
|
||||||
if (profilename && stat(profilename, &stat_file) == -1) {
|
if (profilename && stat(profilename, &stat_file) == -1) {
|
||||||
|
last_error = errno;
|
||||||
PERROR("File %s not found, skipping...\n", profilename);
|
PERROR("File %s not found, skipping...\n", profilename);
|
||||||
continue;
|
if (abort_on_error)
|
||||||
|
break;
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (profilename && S_ISDIR(stat_file.st_mode)) {
|
if (profilename && S_ISDIR(stat_file.st_mode)) {
|
||||||
|
@ -1379,20 +1399,27 @@ int main(int argc, char *argv[])
|
||||||
cb = binary_input ? binary_dir_cb : profile_dir_cb;
|
cb = binary_input ? binary_dir_cb : profile_dir_cb;
|
||||||
if ((retval = dirat_for_each(AT_FDCWD, profilename,
|
if ((retval = dirat_for_each(AT_FDCWD, profilename,
|
||||||
&cb_data, cb))) {
|
&cb_data, cb))) {
|
||||||
|
last_error = errno;
|
||||||
PDEBUG("Failed loading profiles from %s\n",
|
PDEBUG("Failed loading profiles from %s\n",
|
||||||
profilename);
|
profilename);
|
||||||
|
if (abort_on_error)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else if (binary_input) {
|
} else if (binary_input) {
|
||||||
|
/* ignore return as error is handled in work_spawn */
|
||||||
work_spawn(process_binary(option, kernel_interface,
|
work_spawn(process_binary(option, kernel_interface,
|
||||||
profilename),
|
profilename),
|
||||||
handle_work_result);
|
handle_work_result);
|
||||||
} else {
|
} else {
|
||||||
|
/* ignore return as error is handled in work_spawn */
|
||||||
work_spawn(process_profile(option, kernel_interface,
|
work_spawn(process_profile(option, kernel_interface,
|
||||||
profilename, policy_cache),
|
profilename, policy_cache),
|
||||||
handle_work_result);
|
handle_work_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (profilename) free(profilename);
|
cleanup:
|
||||||
|
if (profilename)
|
||||||
|
free(profilename);
|
||||||
profilename = NULL;
|
profilename = NULL;
|
||||||
}
|
}
|
||||||
work_sync(handle_work_result);
|
work_sync(handle_work_result);
|
||||||
|
|
Loading…
Add table
Reference in a new issue