#include <linux/oom.h>
#include <sys/poll.h>
#include <linux/seccomp-bpf.h>
+#include <glob.h>
+#include <libgen.h>
#ifdef HAVE_PAM
#include <security/pam_appl.h>
#include "capability.h"
#include "util.h"
#include "log.h"
+#include "sd-messages.h"
#include "ioprio.h"
#include "securebits.h"
-#include "cgroup.h"
#include "namespace.h"
#include "tcpwrap.h"
#include "exit-status.h"
#include "loopback-setup.h"
#include "path-util.h"
#include "syscall-list.h"
-#include "sd-id128.h"
-#include "sd-messages.h"
+#include "env-util.h"
+#include "fileio.h"
+#include "unit.h"
#define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC)
return 0;
}
-static const char *tty_path(const ExecContext *context) {
+_pure_ static const char *tty_path(const ExecContext *context) {
assert(context);
if (context->tty_path)
vt_disallocate(context->tty_path);
}
+static bool is_terminal_output(ExecOutput o) {
+ return
+ o == EXEC_OUTPUT_TTY ||
+ o == EXEC_OUTPUT_SYSLOG_AND_CONSOLE ||
+ o == EXEC_OUTPUT_KMSG_AND_CONSOLE ||
+ o == EXEC_OUTPUT_JOURNAL_AND_CONSOLE;
+}
+
+void exec_context_serialize(const ExecContext *context, Unit *u, FILE *f) {
+ assert(context);
+ assert(u);
+ assert(f);
+
+ if (context->tmp_dir)
+ unit_serialize_item(u, f, "tmp-dir", context->tmp_dir);
+
+ if (context->var_tmp_dir)
+ unit_serialize_item(u, f, "var-tmp-dir", context->var_tmp_dir);
+}
+
static int open_null_as(int flags, int nfd) {
int fd, r;
static int connect_logger_as(const ExecContext *context, ExecOutput output, const char *ident, const char *unit_id, int nfd) {
int fd, r;
- union sockaddr_union sa;
+ union sockaddr_union sa = {
+ .un.sun_family = AF_UNIX,
+ .un.sun_path = "/run/systemd/journal/stdout",
+ };
assert(context);
assert(output < _EXEC_OUTPUT_MAX);
if (fd < 0)
return -errno;
- zero(sa);
- sa.un.sun_family = AF_UNIX;
- strncpy(sa.un.sun_path, "/run/systemd/journal/stdout", sizeof(sa.un.sun_path));
-
r = connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
if (r < 0) {
close_nointr_nofail(fd);
!!context->syslog_level_prefix,
output == EXEC_OUTPUT_SYSLOG || output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE,
output == EXEC_OUTPUT_KMSG || output == EXEC_OUTPUT_KMSG_AND_CONSOLE,
- output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || output == EXEC_OUTPUT_KMSG_AND_CONSOLE || output == EXEC_OUTPUT_JOURNAL_AND_CONSOLE);
+ is_terminal_output(output));
if (fd != nfd) {
r = dup2(fd, nfd) < 0 ? -errno : nfd;
}
}
-static int setup_output(const ExecContext *context, int socket_fd, const char *ident, const char *unit_id, bool apply_tty_stdin) {
+static int setup_output(const ExecContext *context, int fileno, int socket_fd, const char *ident, const char *unit_id, bool apply_tty_stdin) {
ExecOutput o;
ExecInput i;
+ int r;
assert(context);
assert(ident);
i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
o = fixup_output(context->std_output, socket_fd);
- /* This expects the input is already set up */
+ if (fileno == STDERR_FILENO) {
+ ExecOutput e;
+ e = fixup_output(context->std_error, socket_fd);
- switch (o) {
+ /* This expects the input and output are already set up */
- case EXEC_OUTPUT_INHERIT:
+ /* Don't change the stderr file descriptor if we inherit all
+ * the way and are not on a tty */
+ if (e == EXEC_OUTPUT_INHERIT &&
+ o == EXEC_OUTPUT_INHERIT &&
+ i == EXEC_INPUT_NULL &&
+ !is_terminal_input(context->std_input) &&
+ getppid () != 1)
+ return fileno;
+ /* Duplicate from stdout if possible */
+ if (e == o || e == EXEC_OUTPUT_INHERIT)
+ return dup2(STDOUT_FILENO, fileno) < 0 ? -errno : fileno;
+
+ o = e;
+
+ } else if (o == EXEC_OUTPUT_INHERIT) {
/* If input got downgraded, inherit the original value */
if (i == EXEC_INPUT_NULL && is_terminal_input(context->std_input))
- return open_terminal_as(tty_path(context), O_WRONLY, STDOUT_FILENO);
+ return open_terminal_as(tty_path(context), O_WRONLY, fileno);
/* If the input is connected to anything that's not a /dev/null, inherit that... */
if (i != EXEC_INPUT_NULL)
- return dup2(STDIN_FILENO, STDOUT_FILENO) < 0 ? -errno : STDOUT_FILENO;
+ return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
/* If we are not started from PID 1 we just inherit STDOUT from our parent process. */
if (getppid() != 1)
- return STDOUT_FILENO;
-
- /* We need to open /dev/null here anew, to get the
- * right access mode. So we fall through */
-
- case EXEC_OUTPUT_NULL:
- return open_null_as(O_WRONLY, STDOUT_FILENO);
-
- case EXEC_OUTPUT_TTY:
- if (is_terminal_input(i))
- return dup2(STDIN_FILENO, STDOUT_FILENO) < 0 ? -errno : STDOUT_FILENO;
-
- /* We don't reset the terminal if this is just about output */
- return open_terminal_as(tty_path(context), O_WRONLY, STDOUT_FILENO);
+ return fileno;
- case EXEC_OUTPUT_SYSLOG:
- case EXEC_OUTPUT_SYSLOG_AND_CONSOLE:
- case EXEC_OUTPUT_KMSG:
- case EXEC_OUTPUT_KMSG_AND_CONSOLE:
- case EXEC_OUTPUT_JOURNAL:
- case EXEC_OUTPUT_JOURNAL_AND_CONSOLE:
- return connect_logger_as(context, o, ident, unit_id, STDOUT_FILENO);
-
- case EXEC_OUTPUT_SOCKET:
- assert(socket_fd >= 0);
- return dup2(socket_fd, STDOUT_FILENO) < 0 ? -errno : STDOUT_FILENO;
-
- default:
- assert_not_reached("Unknown output type");
+ /* We need to open /dev/null here anew, to get the right access mode. */
+ return open_null_as(O_WRONLY, fileno);
}
-}
-
-static int setup_error(const ExecContext *context, int socket_fd, const char *ident, const char *unit_id, bool apply_tty_stdin) {
- ExecOutput o, e;
- ExecInput i;
-
- assert(context);
- assert(ident);
-
- i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
- o = fixup_output(context->std_output, socket_fd);
- e = fixup_output(context->std_error, socket_fd);
-
- /* This expects the input and output are already set up */
-
- /* Don't change the stderr file descriptor if we inherit all
- * the way and are not on a tty */
- if (e == EXEC_OUTPUT_INHERIT &&
- o == EXEC_OUTPUT_INHERIT &&
- i == EXEC_INPUT_NULL &&
- !is_terminal_input(context->std_input) &&
- getppid () != 1)
- return STDERR_FILENO;
- /* Duplicate from stdout if possible */
- if (e == o || e == EXEC_OUTPUT_INHERIT)
- return dup2(STDOUT_FILENO, STDERR_FILENO) < 0 ? -errno : STDERR_FILENO;
-
- switch (e) {
+ switch (o) {
case EXEC_OUTPUT_NULL:
- return open_null_as(O_WRONLY, STDERR_FILENO);
+ return open_null_as(O_WRONLY, fileno);
case EXEC_OUTPUT_TTY:
if (is_terminal_input(i))
- return dup2(STDIN_FILENO, STDERR_FILENO) < 0 ? -errno : STDERR_FILENO;
+ return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
/* We don't reset the terminal if this is just about output */
- return open_terminal_as(tty_path(context), O_WRONLY, STDERR_FILENO);
+ return open_terminal_as(tty_path(context), O_WRONLY, fileno);
case EXEC_OUTPUT_SYSLOG:
case EXEC_OUTPUT_SYSLOG_AND_CONSOLE:
case EXEC_OUTPUT_KMSG_AND_CONSOLE:
case EXEC_OUTPUT_JOURNAL:
case EXEC_OUTPUT_JOURNAL_AND_CONSOLE:
- return connect_logger_as(context, e, ident, unit_id, STDERR_FILENO);
+ r = connect_logger_as(context, o, ident, unit_id, fileno);
+ if (r < 0) {
+ log_struct_unit(LOG_CRIT, unit_id,
+ "MESSAGE=Failed to connect std%s of %s to the journal socket: %s",
+ fileno == STDOUT_FILENO ? "out" : "err",
+ unit_id, strerror(-r),
+ "ERRNO=%d", -r,
+ NULL);
+ r = open_null_as(O_WRONLY, fileno);
+ }
+ return r;
case EXEC_OUTPUT_SOCKET:
assert(socket_fd >= 0);
- return dup2(socket_fd, STDERR_FILENO) < 0 ? -errno : STDERR_FILENO;
+ return dup2(socket_fd, fileno) < 0 ? -errno : fileno;
default:
assert_not_reached("Unknown error type");
return r;
}
-static int write_confirm_message(const char *format, ...) {
+_printf_attr_(1, 2) static int write_confirm_message(const char *format, ...) {
int fd;
va_list ap;
/* First step: If we need to keep capabilities but
* drop privileges we need to make sure we keep our
- * caps, whiel we drop privileges. */
+ * caps, while we drop privileges. */
if (uid != 0) {
- int sb = context->secure_bits|SECURE_KEEP_CAPS;
+ int sb = context->secure_bits | 1<<SECURE_KEEP_CAPS;
if (prctl(PR_GET_SECUREBITS) != sb)
if (prctl(PR_SET_SECUREBITS, sb) < 0)
int i;
unsigned n;
struct sock_filter *f;
- struct sock_fprog prog;
+ struct sock_fprog prog = {};
assert(syscall_filter);
for (i = 0, n = 0; i < syscall_max(); i++)
if (syscall_filter[i >> 4] & (1 << (i & 31))) {
struct sock_filter item[] = {
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, i, 0, 1),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, INDEX_TO_SYSCALL(i), 0, 1),
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
};
memcpy(f + (ELEMENTSOF(header) + 2*n), footer, sizeof(footer));
/* Third: install the filter */
- zero(prog);
prog.len = ELEMENTSOF(header) + ELEMENTSOF(footer) + 2*n;
prog.filter = f;
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0)
int exec_spawn(ExecCommand *command,
char **argv,
- const ExecContext *context,
+ ExecContext *context,
int fds[], unsigned n_fds,
char **environment,
bool apply_permissions,
bool apply_chroot,
bool apply_tty_stdin,
bool confirm_spawn,
- CGroupBonding *cgroup_bondings,
- CGroupAttribute *cgroup_attributes,
- const char *cgroup_suffix,
+ CGroupControllerMask cgroup_mask,
+ const char *cgroup_path,
const char *unit_id,
int idle_pipe[2],
pid_t *ret) {
+ _cleanup_strv_free_ char **files_env = NULL;
+ int socket_fd;
+ char *line;
pid_t pid;
int r;
- char *line;
- int socket_fd;
- char _cleanup_strv_free_ **files_env = NULL;
assert(command);
assert(context);
r = exec_context_load_environment(context, &files_env);
if (r < 0) {
- log_struct(LOG_ERR,
- "UNIT=%s", unit_id,
+ log_struct_unit(LOG_ERR,
+ unit_id,
"MESSAGE=Failed to load environment files: %s", strerror(-r),
"ERRNO=%d", -r,
NULL);
if (!line)
return log_oom();
- log_struct(LOG_DEBUG,
- "UNIT=%s", unit_id,
- "MESSAGE=About to execute %s", line,
- NULL);
+ log_struct_unit(LOG_DEBUG,
+ unit_id,
+ "EXECUTABLE=%s", command->path,
+ "MESSAGE=About to execute: %s", line,
+ NULL);
free(line);
- r = cgroup_bonding_realize_list(cgroup_bondings);
- if (r < 0)
- return r;
-
- cgroup_attribute_apply_list(cgroup_attributes, cgroup_bondings);
+ if (context->private_tmp && !context->tmp_dir && !context->var_tmp_dir) {
+ r = setup_tmpdirs(&context->tmp_dir, &context->var_tmp_dir);
+ if (r < 0)
+ return r;
+ }
pid = fork();
if (pid < 0)
const char *username = NULL, *home = NULL;
uid_t uid = (uid_t) -1;
gid_t gid = (gid_t) -1;
- char _cleanup_strv_free_ **our_env = NULL, **pam_env = NULL,
+ _cleanup_strv_free_ char **our_env = NULL, **pam_env = NULL,
**final_env = NULL, **final_argv = NULL;
unsigned n_env = 0;
- bool set_access = false;
/* child */
goto fail_child;
}
- err = setup_output(context, socket_fd, path_get_file_name(command->path), unit_id, apply_tty_stdin);
+ err = setup_output(context, STDOUT_FILENO, socket_fd, path_get_file_name(command->path), unit_id, apply_tty_stdin);
if (err < 0) {
r = EXIT_STDOUT;
goto fail_child;
}
- err = setup_error(context, socket_fd, path_get_file_name(command->path), unit_id, apply_tty_stdin);
+ err = setup_output(context, STDERR_FILENO, socket_fd, path_get_file_name(command->path), unit_id, apply_tty_stdin);
if (err < 0) {
r = EXIT_STDERR;
goto fail_child;
}
- if (cgroup_bondings) {
- err = cgroup_bonding_install_list(cgroup_bondings, 0, cgroup_suffix);
+ if (cgroup_path) {
+ err = cg_attach_with_mask(cgroup_mask, cgroup_path, 0);
if (err < 0) {
r = EXIT_CGROUP;
goto fail_child;
snprintf(t, sizeof(t), "%i", context->oom_score_adjust);
char_array_0(t);
- if (write_one_line_file("/proc/self/oom_score_adj", t) < 0) {
+ if (write_string_file("/proc/self/oom_score_adj", t) < 0) {
err = -errno;
r = EXIT_OOM_ADJUST;
goto fail_child;
}
if (context->cpu_sched_set) {
- struct sched_param param;
-
- zero(param);
- param.sched_priority = context->cpu_sched_priority;
+ struct sched_param param = {
+ .sched_priority = context->cpu_sched_priority,
+ };
- if (sched_setscheduler(0, context->cpu_sched_policy |
- (context->cpu_sched_reset_on_fork ? SCHED_RESET_ON_FORK : 0), ¶m) < 0) {
+ r = sched_setscheduler(0,
+ context->cpu_sched_policy |
+ (context->cpu_sched_reset_on_fork ?
+ SCHED_RESET_ON_FORK : 0),
+ ¶m);
+ if (r < 0) {
err = -errno;
r = EXIT_SETSCHEDULER;
goto fail_child;
goto fail_child;
}
}
-
- if (cgroup_bondings && context->control_group_modify) {
- err = cgroup_bonding_set_group_access_list(cgroup_bondings, 0755, uid, gid);
- if (err >= 0)
- err = cgroup_bonding_set_task_access_list(cgroup_bondings, 0644, uid, gid, context->control_group_persistent);
- if (err < 0) {
- r = EXIT_CGROUP;
- goto fail_child;
- }
-
- set_access = true;
- }
- }
-
- if (cgroup_bondings && !set_access && context->control_group_persistent >= 0) {
- err = cgroup_bonding_set_task_access_list(cgroup_bondings, (mode_t) -1, (uid_t) -1, (uid_t) -1, context->control_group_persistent);
- if (err < 0) {
- r = EXIT_CGROUP;
- goto fail_child;
- }
}
if (apply_permissions) {
err = setup_namespace(context->read_write_dirs,
context->read_only_dirs,
context->inaccessible_dirs,
+ context->tmp_dir,
+ context->var_tmp_dir,
context->private_tmp,
context->mount_flags);
if (err < 0) {
goto fail_child;
}
} else {
- char _cleanup_free_ *d = NULL;
+ _cleanup_free_ char *d = NULL;
if (asprintf(&d, "%s/%s",
context->root_directory ? context->root_directory : "",
}
}
- if (!(our_env = new0(char*, 7))) {
+ our_env = new0(char*, 7);
+ if (!our_env) {
err = -ENOMEM;
r = EXIT_MEMORY;
goto fail_child;
assert(n_env <= 7);
- if (!(final_env = strv_env_merge(
- 5,
- environment,
- our_env,
- context->environment,
- files_env,
- pam_env,
- NULL))) {
+ final_env = strv_env_merge(5,
+ environment,
+ our_env,
+ context->environment,
+ files_env,
+ pam_env,
+ NULL);
+ if (!final_env) {
err = -ENOMEM;
r = EXIT_MEMORY;
goto fail_child;
}
- if (!(final_argv = replace_env_argv(argv, final_env))) {
+ final_argv = replace_env_argv(argv, final_env);
+ if (!final_argv) {
err = -ENOMEM;
r = EXIT_MEMORY;
goto fail_child;
final_env = strv_env_clean(final_env);
+ if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
+ line = exec_command_line(final_argv);
+ if (line) {
+ log_open();
+ log_struct_unit(LOG_DEBUG,
+ unit_id,
+ "EXECUTABLE=%s", command->path,
+ "MESSAGE=Executing: %s", line,
+ NULL);
+ log_close();
+ free(line);
+ line = NULL;
+ }
+ }
execve(command->path, final_argv, final_env);
err = -errno;
r = EXIT_EXEC;
_exit(r);
}
- log_struct(LOG_DEBUG,
- "UNIT=%s", unit_id,
- "MESSAGE=Forked %s as %lu",
- command->path, (unsigned long) pid,
- NULL);
+ log_struct_unit(LOG_DEBUG,
+ unit_id,
+ "MESSAGE=Forked %s as %lu",
+ command->path, (unsigned long) pid,
+ NULL);
/* We add the new process to the cgroup both in the child (so
* that we can be sure that no user code is ever executed
* outside of the cgroup) and in the parent (so that we can be
* sure that when we kill the cgroup the process will be
* killed too). */
- if (cgroup_bondings)
- cgroup_bonding_install_list(cgroup_bondings, pid, cgroup_suffix);
+ if (cgroup_path)
+ cg_attach(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, pid);
exec_status_start(&command->exec_status, pid);
c->cpu_sched_policy = SCHED_OTHER;
c->syslog_priority = LOG_DAEMON|LOG_INFO;
c->syslog_level_prefix = true;
- c->control_group_persistent = -1;
c->ignore_sigpipe = true;
c->timer_slack_nsec = (nsec_t) -1;
}
-void exec_context_done(ExecContext *c) {
+void exec_context_tmp_dirs_done(ExecContext *c) {
+ char* dirs[] = {c->tmp_dir ? c->tmp_dir : c->var_tmp_dir,
+ c->tmp_dir ? c->var_tmp_dir : NULL,
+ NULL};
+ char **dirp;
+
+ for(dirp = dirs; *dirp; dirp++) {
+ char *dir;
+ int r;
+
+ r = rm_rf_dangerous(*dirp, false, true, false);
+ dir = dirname(*dirp);
+ if (r < 0)
+ log_warning("Failed to remove content of temporary directory %s: %s",
+ dir, strerror(-r));
+ else {
+ r = rmdir(dir);
+ if (r < 0)
+ log_warning("Failed to remove temporary directory %s: %s",
+ dir, strerror(-r));
+ }
+
+ free(*dirp);
+ }
+
+ c->tmp_dir = c->var_tmp_dir = NULL;
+}
+
+void exec_context_done(ExecContext *c, bool reloading_or_reexecuting) {
unsigned l;
assert(c);
free(c->syscall_filter);
c->syscall_filter = NULL;
+
+ if (!reloading_or_reexecuting)
+ exec_context_tmp_dirs_done(c);
}
void exec_command_done(ExecCommand *c) {
int k;
bool ignore = false;
char **p;
+ _cleanup_globfree_ glob_t pglob = {};
+ int count, n;
fn = *i;
}
if (!path_is_absolute(fn)) {
-
if (ignore)
continue;
return -EINVAL;
}
- if ((k = load_env_file(fn, &p)) < 0) {
-
+ /* Filename supports globbing, take all matching files */
+ errno = 0;
+ if (glob(fn, 0, NULL, &pglob) != 0) {
if (ignore)
continue;
strv_free(r);
- return k;
+ return errno ? -errno : -EINVAL;
}
+ count = pglob.gl_pathc;
+ if (count == 0) {
+ if (ignore)
+ continue;
- if (r == NULL)
- r = p;
- else {
- char **m;
-
- m = strv_env_merge(2, r, p);
strv_free(r);
- strv_free(p);
-
- if (!m)
- return -ENOMEM;
+ return -EINVAL;
+ }
+ for (n = 0; n < count; n++) {
+ k = load_env_file(pglob.gl_pathv[n], NULL, &p);
+ if (k < 0) {
+ if (ignore)
+ continue;
- r = m;
+ strv_free(r);
+ return k;
+ }
+ /* Log invalid environment variables with filename */
+ if (p)
+ p = strv_env_clean_log(p, pglob.gl_pathv[n]);
+
+ if (r == NULL)
+ r = p;
+ else {
+ char **m;
+
+ m = strv_env_merge(2, r, p);
+ strv_free(r);
+ strv_free(p);
+ if (!m)
+ return -ENOMEM;
+
+ r = m;
+ }
}
}
return 0;
}
+static bool tty_may_match_dev_console(const char *tty) {
+ char *active = NULL, *console;
+ bool b;
+
+ if (startswith(tty, "/dev/"))
+ tty += 5;
+
+ /* trivial identity? */
+ if (streq(tty, "console"))
+ return true;
+
+ console = resolve_dev_console(&active);
+ /* if we could not resolve, assume it may */
+ if (!console)
+ return true;
+
+ /* "tty0" means the active VC, so it may be the same sometimes */
+ b = streq(console, tty) || (streq(console, "tty0") && tty_is_vc(tty));
+ free(active);
+
+ return b;
+}
+
+bool exec_context_may_touch_console(ExecContext *ec) {
+ return (ec->tty_reset || ec->tty_vhangup || ec->tty_vt_disallocate ||
+ is_terminal_input(ec->std_input) ||
+ is_terminal_output(ec->std_output) ||
+ is_terminal_output(ec->std_error)) &&
+ tty_may_match_dev_console(tty_path(ec));
+}
+
static void strv_fprintf(FILE *f, char **l) {
char **g;
}
void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
- char ** e;
+ char **e;
unsigned i;
assert(c);
assert(f);
- if (!prefix)
- prefix = "";
+ prefix = strempty(prefix);
fprintf(f,
"%sUMask: %04o\n"
"%sRootDirectory: %s\n"
"%sNonBlocking: %s\n"
"%sPrivateTmp: %s\n"
- "%sControlGroupModify: %s\n"
- "%sControlGroupPersistent: %s\n"
"%sPrivateNetwork: %s\n"
"%sIgnoreSIGPIPE: %s\n",
prefix, c->umask,
prefix, c->root_directory ? c->root_directory : "/",
prefix, yes_no(c->non_blocking),
prefix, yes_no(c->private_tmp),
- prefix, yes_no(c->control_group_modify),
- prefix, yes_no(c->control_group_persistent),
prefix, yes_no(c->private_network),
prefix, yes_no(c->ignore_sigpipe));
prefix, c->cpu_sched_priority,
prefix, yes_no(c->cpu_sched_reset_on_fork));
free(policy_str);
- }
+ }
if (c->cpuset) {
fprintf(f, "%sCPUAffinity:", prefix);
if (c->secure_bits)
fprintf(f, "%sSecure Bits:%s%s%s%s%s%s\n",
prefix,
- (c->secure_bits & SECURE_KEEP_CAPS) ? " keep-caps" : "",
- (c->secure_bits & SECURE_KEEP_CAPS_LOCKED) ? " keep-caps-locked" : "",
- (c->secure_bits & SECURE_NO_SETUID_FIXUP) ? " no-setuid-fixup" : "",
- (c->secure_bits & SECURE_NO_SETUID_FIXUP_LOCKED) ? " no-setuid-fixup-locked" : "",
- (c->secure_bits & SECURE_NOROOT) ? " noroot" : "",
- (c->secure_bits & SECURE_NOROOT_LOCKED) ? "noroot-locked" : "");
+ (c->secure_bits & 1<<SECURE_KEEP_CAPS) ? " keep-caps" : "",
+ (c->secure_bits & 1<<SECURE_KEEP_CAPS_LOCKED) ? " keep-caps-locked" : "",
+ (c->secure_bits & 1<<SECURE_NO_SETUID_FIXUP) ? " no-setuid-fixup" : "",
+ (c->secure_bits & 1<<SECURE_NO_SETUID_FIXUP_LOCKED) ? " no-setuid-fixup-locked" : "",
+ (c->secure_bits & 1<<SECURE_NOROOT) ? " noroot" : "",
+ (c->secure_bits & 1<<SECURE_NOROOT_LOCKED) ? "noroot-locked" : "");
if (c->capability_bounding_set_drop) {
unsigned long l;