Merge pull request #148 from kernelmethod/apparmor_support
Add AppArmor support to sudo
This commit is contained in:
@@ -375,6 +375,10 @@ Defaults are listed in brackets after the description.
|
||||
ldap_sasl_interactive_bind_s() function is present in the
|
||||
LDAP libraries.
|
||||
|
||||
--with-apparmor
|
||||
Enable support for the AppArmor Linux Security Module (LSM) on
|
||||
supported systems.
|
||||
|
||||
--with-logincap
|
||||
This adds support for login classes specified in `/etc/login.conf`.
|
||||
It is enabled by default on BSD/OS, Darwin, FreeBSD, OpenBSD, and
|
||||
|
1
MANIFEST
1
MANIFEST
@@ -1178,6 +1178,7 @@ scripts/mkpkg
|
||||
scripts/pp
|
||||
scripts/unanon
|
||||
src/Makefile.in
|
||||
src/apparmor.c
|
||||
src/conversation.c
|
||||
src/copy_file.c
|
||||
src/edit_open.c
|
||||
|
@@ -51,6 +51,9 @@
|
||||
/* Define to 1 if you use AIX general authentication. */
|
||||
#undef HAVE_AIXAUTH
|
||||
|
||||
/* Define to 1 to enable AppArmor support. */
|
||||
#undef HAVE_APPARMOR
|
||||
|
||||
/* Define to 1 if you have the `arc4random' function. */
|
||||
#undef HAVE_ARC4RANDOM
|
||||
|
||||
|
16
configure.ac
16
configure.ac
@@ -67,6 +67,7 @@ AC_SUBST([BAMAN])
|
||||
AC_SUBST([LCMAN])
|
||||
AC_SUBST([PSMAN])
|
||||
AC_SUBST([SEMAN])
|
||||
AC_SUBST([AAMAN])
|
||||
AC_SUBST([devdir])
|
||||
AC_SUBST([mansectsu])
|
||||
AC_SUBST([mansectform])
|
||||
@@ -251,6 +252,7 @@ BAMAN=0
|
||||
LCMAN=0
|
||||
PSMAN=0
|
||||
SEMAN=0
|
||||
AAMAN=0
|
||||
LIBINTL=
|
||||
LIBCRYPTO=
|
||||
LIBMD=
|
||||
@@ -1483,6 +1485,19 @@ AC_ARG_WITH(selinux, [AS_HELP_STRING([--with-selinux], [enable SELinux support])
|
||||
;;
|
||||
esac], [with_selinux=no])
|
||||
|
||||
AC_ARG_WITH(apparmor, [AS_HELP_STRING([--with-apparmor], [enable AppArmor support])],
|
||||
[case $with_apparmor in
|
||||
yes) AC_DEFINE(HAVE_APPARMOR)
|
||||
AAMAN=1
|
||||
SUDO_OBJS="${SUDO_OBJS} apparmor.o"
|
||||
AC_CHECK_LIB(apparmor, aa_change_profile,
|
||||
[SUDO_LIBS="${SUDO_LIBS} -lapparmor"])
|
||||
;;
|
||||
no) ;;
|
||||
*) AC_MSG_ERROR([--with-apparmor does not take an argument.])
|
||||
|
||||
esac], [with_apparmor=no])
|
||||
|
||||
AC_ARG_ENABLE(sasl,
|
||||
[AS_HELP_STRING([--enable-sasl], [Enable/disable LDAP SASL support])],
|
||||
[ case "$enableval" in
|
||||
@@ -5416,6 +5431,7 @@ AH_TEMPLATE(HAVE_PROJECT_H, [Define to 1 if you have the <project.h> header file
|
||||
AH_TEMPLATE(HAVE_SECURID, [Define to 1 if you use SecurID for authentication.])
|
||||
AH_TEMPLATE(HAVE_SELINUX, [Define to 1 to enable SELinux RBAC support.])
|
||||
AH_TEMPLATE(HAVE_SETKEYCREATECON, [Define to 1 if you have the `setkeycreatecon' function.])
|
||||
AH_TEMPLATE(HAVE_APPARMOR, [Define to 1 to enable AppArmor support.])
|
||||
AH_TEMPLATE(HAVE_SHL_LOAD, [Define to 1 if you have the `shl_load' function.])
|
||||
AH_TEMPLATE(HAVE_SKEY, [Define to 1 if you use S/Key.])
|
||||
AH_TEMPLATE(HAVE_SKEYACCESS, [Define to 1 if your S/Key library has skeyaccess().])
|
||||
|
@@ -5,5 +5,6 @@ RUN DEBIAN_FRONTEND=noninteractive TZ=America/Denver apt-get update && \
|
||||
build-essential curl dpkg-dev ed libldap2-dev libpam0g-dev \
|
||||
libsasl2-dev libselinux1-dev libsepol1-dev libssl-dev zlib1g-dev \
|
||||
libaudit-dev libssl-dev python3-dev libpython3-dev libwolfssl-dev \
|
||||
libapparmor-dev \
|
||||
file lsb-release fakeroot pkg-config procps git ssh openssh-client
|
||||
RUN useradd -ms /bin/bash build
|
||||
|
@@ -5,5 +5,6 @@ RUN DEBIAN_FRONTEND=noninteractive TZ=America/Denver apt-get update && \
|
||||
build-essential curl dpkg-dev ed libldap2-dev libpam0g-dev \
|
||||
libsasl2-dev libselinux1-dev libsepol1-dev libssl-dev zlib1g-dev \
|
||||
libaudit-dev libssl-dev python3-dev libpython3-dev libwolfssl-dev \
|
||||
libapparmor-dev \
|
||||
file lsb-release fakeroot pkg-config procps git ssh openssh-client
|
||||
RUN useradd -ms /bin/bash build
|
||||
|
@@ -5,5 +5,6 @@ RUN DEBIAN_FRONTEND=noninteractive TZ=America/Denver apt-get update && \
|
||||
build-essential curl dpkg-dev ed libldap2-dev libpam0g-dev \
|
||||
libsasl2-dev libselinux1-dev libsepol1-dev libssl-dev zlib1g-dev \
|
||||
libaudit-dev libssl-dev python3-dev libpython3-dev libwolfssl-dev \
|
||||
libapparmor-dev \
|
||||
file lsb-release fakeroot pkg-config procps git ssh openssh-client
|
||||
RUN useradd -ms /bin/bash build
|
||||
|
@@ -5,5 +5,6 @@ RUN DEBIAN_FRONTEND=noninteractive TZ=America/Denver apt-get update && \
|
||||
build-essential curl dpkg-dev ed libldap2-dev libpam0g-dev \
|
||||
libsasl2-dev libselinux1-dev libsepol1-dev libssl-dev zlib1g-dev \
|
||||
libaudit-dev libssl-dev python3-dev libpython3-dev libwolfssl-dev \
|
||||
libapparmor-dev \
|
||||
file lsb-release fakeroot pkg-config procps git ssh openssh-client
|
||||
RUN useradd -ms /bin/bash build
|
||||
|
@@ -5,5 +5,6 @@ RUN DEBIAN_FRONTEND=noninteractive TZ=America/Denver apt-get update && \
|
||||
build-essential curl dpkg-dev ed libldap2-dev libpam0g-dev \
|
||||
libsasl2-dev libselinux1-dev libsepol1-dev libssl-dev zlib1g-dev \
|
||||
libaudit-dev libssl-dev python3-dev libpython3-dev libwolfssl-dev \
|
||||
libapparmor-dev \
|
||||
file lsb-release fakeroot pkg-config procps git ssh openssh-client
|
||||
RUN useradd -ms /bin/bash build
|
||||
|
@@ -1290,6 +1290,8 @@ Runas_Spec ::= '(' Runas_List? (':' Runas_List)? ')'
|
||||
SELinux_Spec ::= ('ROLE=role' | 'TYPE=type')
|
||||
|
||||
.\}
|
||||
AppArmor_Spec ::= 'APPARMOR_PROFILE=profile'
|
||||
|
||||
.if \n(PS \{\
|
||||
Solaris_Priv_Spec ::= ('PRIVS=privset' | 'LIMITPRIVS=privset')
|
||||
|
||||
@@ -1503,6 +1505,7 @@ Options may consist of
|
||||
.if \n(SL \{\
|
||||
SELinux roles and/or types,
|
||||
.\}
|
||||
AppArmor profiles,
|
||||
.if \n(PS \{\
|
||||
Solaris privileges sets,
|
||||
.\}
|
||||
@@ -1533,6 +1536,59 @@ A role or type specified on the command line,
|
||||
however, will supersede the values in
|
||||
\fIsudoers\fR.
|
||||
.\}
|
||||
.SS "AppArmor_Spec"
|
||||
On systems supporting AppArmor,
|
||||
\fIsudoers\fR
|
||||
file entries may optionally specify an AppArmor profile that should be
|
||||
used to confine a command.
|
||||
If an AppArmor profile is specified with the command, it will override
|
||||
any default values specified in
|
||||
\fIsudoers\fR.
|
||||
Appropriate profile transition rules must be defined to support the
|
||||
profile change specified for a user.
|
||||
.PP
|
||||
AppArmor profiles can be specified in any way that complies with the
|
||||
rules of
|
||||
aa_change_profile(2).
|
||||
For instance, in the following
|
||||
\fIsudoers\fR
|
||||
entry
|
||||
.nf
|
||||
.sp
|
||||
.RS 0n
|
||||
alice ALL = (root) APPARMOR_PROFILE=my-profile ALL
|
||||
.RE
|
||||
.fi
|
||||
.PP
|
||||
the user
|
||||
\fBalice\fR
|
||||
may run any command as root under confinement by the profile
|
||||
\(oqmy-profile\(cq.
|
||||
You can also stack profiles, or allow a user to run commands unconfined by
|
||||
any profile. E.g.,
|
||||
.nf
|
||||
.sp
|
||||
.RS 0n
|
||||
bob ALL = (root) APPARMOR_PROFILE=foo//&bar /usr/bin/vi
|
||||
cathy ALL = (root) APPARMOR_PROFILE=unconfined /bin/ls
|
||||
.RE
|
||||
.fi
|
||||
.PP
|
||||
These
|
||||
\fIsudoers\fR
|
||||
entries allow user
|
||||
\fBbob\fR
|
||||
to run
|
||||
\fI/usr/bin/vi\fR
|
||||
as root under the stacked profiles
|
||||
\(oqfoo\(cq
|
||||
and
|
||||
\(oqbar\(cq,
|
||||
and user
|
||||
\fBcathy\fR
|
||||
to run
|
||||
\fI/bin/ls\fR
|
||||
without any confinement at all.
|
||||
.if \n(PS \{\
|
||||
.SS "Solaris_Priv_Spec"
|
||||
On Solaris systems,
|
||||
@@ -4161,6 +4217,19 @@ which does not create a new PAM session.
|
||||
.PP
|
||||
\fBStrings\fR:
|
||||
.TP 18n
|
||||
apparmor_profile
|
||||
The default AppArmor profile to transition into when executing the
|
||||
command.
|
||||
The default
|
||||
\fIapparmor_profile\fR
|
||||
can be overriden for individual
|
||||
\fIsudoers\fR
|
||||
entries by specifying the
|
||||
\fIAPPARMOR_PROFILE\fR
|
||||
option.
|
||||
This option is only available when sudo is built with AppArmor
|
||||
support.
|
||||
.TP 18n
|
||||
authfail_message
|
||||
Message that is displayed after a user fails to authenticate.
|
||||
The message may include the
|
||||
|
@@ -21,6 +21,7 @@
|
||||
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
.\"
|
||||
.nr SL @SEMAN@
|
||||
.nr AA @AAMAN@
|
||||
.nr BA @BAMAN@
|
||||
.nr LC @LCMAN@
|
||||
.nr PS @PSMAN@
|
||||
@@ -1231,13 +1232,23 @@ Runas_Spec ::= '(' Runas_List? (':' Runas_List)? ')'
|
||||
.el Option_Spec ::= (SELinux_Spec | Date_Spec | Timeout_Spec | Chdir_Spec | Chroot_Spec)
|
||||
.\}
|
||||
.el \{\
|
||||
.ie \n(AA \{\
|
||||
.ie \n(PS Option_Spec ::= (AppArmor_Spec | Solaris_Priv_Spec | Date_Spec | Timeout_Spec | Chdir_Spec | Chroot_Spec)
|
||||
.el Option_Spec ::= (AppArmor_Spec | Date_Spec | Timeout_Spec | Chdir_Spec | Chroot_Spec)
|
||||
.\}
|
||||
.el \{\
|
||||
.ie \n(PS Option_Spec ::= (Solaris_Priv_Spec | Date_Spec | Timeout_Spec | Chdir_Spec | Chroot_Spec)
|
||||
.el Option_Spec ::= (Date_Spec | Timeout_Spec | Chdir_Spec | Chroot_Spec)
|
||||
.\}
|
||||
.\}
|
||||
|
||||
.if \n(SL \{\
|
||||
SELinux_Spec ::= ('ROLE=role' | 'TYPE=type')
|
||||
|
||||
.\}
|
||||
.if \n(AA \{\
|
||||
AppArmor_Spec ::= 'APPARMOR_PROFILE=profile'
|
||||
|
||||
.\}
|
||||
.if \n(PS \{\
|
||||
Solaris_Priv_Spec ::= ('PRIVS=privset' | 'LIMITPRIVS=privset')
|
||||
@@ -1427,6 +1438,9 @@ Options may consist of
|
||||
.if \n(SL \{\
|
||||
SELinux roles and/or types,
|
||||
.\}
|
||||
.if \n(AA \{\
|
||||
AppArmor profiles,
|
||||
.\}
|
||||
.if \n(PS \{\
|
||||
Solaris privileges sets,
|
||||
.\}
|
||||
@@ -1457,6 +1471,55 @@ A role or type specified on the command line,
|
||||
however, will supersede the values in
|
||||
.Em sudoers .
|
||||
.\}
|
||||
.if \n(AA \{\
|
||||
.Ss AppArmor_Spec
|
||||
On systems supporting AppArmor,
|
||||
.Em sudoers
|
||||
file entries may optionally specify an AppArmor profile that should be
|
||||
used to confine a command.
|
||||
If an AppArmor profile is specified with the command, it will override
|
||||
any default values specified in
|
||||
.Em sudoers .
|
||||
Appropriate profile transition rules must be defined to support the
|
||||
profile change specified for a user.
|
||||
.Pp
|
||||
AppArmor profiles can be specified in any way that complies with the
|
||||
rules of
|
||||
.Xr aa_change_profile 2 .
|
||||
For instance, in the following
|
||||
.Em sudoers
|
||||
entry
|
||||
.Bd -literal
|
||||
alice ALL = (root) APPARMOR_PROFILE=my-profile ALL
|
||||
.Ed
|
||||
.Pp
|
||||
the user
|
||||
.Sy alice
|
||||
may run any command as root under confinement by the profile
|
||||
.Ql my-profile .
|
||||
You can also stack profiles, or allow a user to run commands unconfined by
|
||||
any profile. E.g.,
|
||||
.Bd -literal
|
||||
bob ALL = (root) APPARMOR_PROFILE=foo//&bar /usr/bin/vi
|
||||
cathy ALL = (root) APPARMOR_PROFILE=unconfined /bin/ls
|
||||
.Ed
|
||||
.Pp
|
||||
These
|
||||
.Em sudoers
|
||||
entries allow user
|
||||
.Sy bob
|
||||
to run
|
||||
.Pa /usr/bin/vi
|
||||
as root under the stacked profiles
|
||||
.Ql foo
|
||||
and
|
||||
.Ql bar ,
|
||||
and user
|
||||
.Sy cathy
|
||||
to run
|
||||
.Pa /bin/ls
|
||||
without any confinement at all.
|
||||
.\}
|
||||
.if \n(PS \{\
|
||||
.Ss Solaris_Priv_Spec
|
||||
On Solaris systems,
|
||||
@@ -3931,6 +3994,20 @@ which does not create a new PAM session.
|
||||
.Pp
|
||||
.Sy Strings :
|
||||
.Bl -tag -width 16n
|
||||
.if \n(AA \{\
|
||||
.It apparmor_profile
|
||||
The default AppArmor profile to transition into when executing the
|
||||
command.
|
||||
The default
|
||||
.Em apparmor_profile
|
||||
can be overriden for individual
|
||||
.Em sudoers
|
||||
entries by specifying the
|
||||
.Em APPARMOR_PROFILE
|
||||
option.
|
||||
This option is only available when sudo is built with AppArmor
|
||||
support.
|
||||
.\}
|
||||
.It authfail_message
|
||||
Message that is displayed after a user fails to authenticate.
|
||||
The message may include the
|
||||
|
@@ -85,6 +85,7 @@ struct sudo_conf_debug_file_list;
|
||||
#define SUDO_DEBUG_SELINUX (12<<6) /* selinux */
|
||||
#define SUDO_DEBUG_UTIL (13<<6) /* utility functions */
|
||||
#define SUDO_DEBUG_UTMP (14<<6) /* utmp file ops */
|
||||
#define SUDO_DEBUG_APPARMOR (15<<6) /* AppArmor */
|
||||
#define SUDO_DEBUG_ALL 0xffff0000 /* all subsystems */
|
||||
|
||||
/* Error return for sudo_debug_register(). */
|
||||
|
@@ -190,6 +190,9 @@ check_user(int validated, int mode)
|
||||
#ifdef HAVE_SELINUX
|
||||
if (user_role == NULL && user_type == NULL)
|
||||
#endif
|
||||
#ifdef HAVE_APPARMOR
|
||||
if (user_apparmor_profile == NULL)
|
||||
#endif
|
||||
#ifdef HAVE_PRIV_SET
|
||||
if (runas_privs == NULL && runas_limitprivs == NULL)
|
||||
#endif
|
||||
|
@@ -553,6 +553,14 @@ print_cmndspec_csv(FILE *fp, struct sudoers_parse_tree *parse_tree,
|
||||
}
|
||||
#endif /* HAVE_SELINUX */
|
||||
|
||||
#ifdef HAVE_APPARMOR
|
||||
if (cs->apparmor_profile != NULL) {
|
||||
fprintf(fp, "%sapparmor_profile=%s,", need_comma ? "," : "",
|
||||
cs->apparmor_profile);
|
||||
need_comma = true;
|
||||
}
|
||||
#endif /* HAVE_APPARMOR */
|
||||
|
||||
#ifdef HAVE_PRIV_SET
|
||||
/* Print Solaris privs/limitprivs */
|
||||
if (cs->privs != NULL || cs->limitprivs != NULL) {
|
||||
@@ -571,7 +579,7 @@ print_cmndspec_csv(FILE *fp, struct sudoers_parse_tree *parse_tree,
|
||||
|
||||
/*
|
||||
* Merge adjacent commands with matching tags, runas, SELinux
|
||||
* role/type and Solaris priv settings.
|
||||
* role/type, AppArmor profiles and Solaris priv settings.
|
||||
*/
|
||||
for (;;) {
|
||||
/* Does the next entry differ only in the command itself? */
|
||||
@@ -585,6 +593,9 @@ print_cmndspec_csv(FILE *fp, struct sudoers_parse_tree *parse_tree,
|
||||
#ifdef HAVE_SELINUX
|
||||
|| cs->role != next->role || cs->type != next->type
|
||||
#endif /* HAVE_SELINUX */
|
||||
#ifdef HAVE_APPARMOR
|
||||
|| cs->apparmor_profile != next->apparmor_profile
|
||||
#endif /* HAVE_APPARMOR */
|
||||
|| cs->runchroot != next->runchroot || cs->runcwd != next->runcwd;
|
||||
|
||||
if (!quoted && !last_one) {
|
||||
|
@@ -581,6 +581,9 @@ cmndspec_continues(struct cmndspec *cs, struct cmndspec *next)
|
||||
#ifdef HAVE_SELINUX
|
||||
&& cs->role == next->role && cs->type == next->type
|
||||
#endif /* HAVE_SELINUX */
|
||||
#ifdef HAVE_APPARMOR
|
||||
&& cs->apparmor_profile == next->apparmor_profile
|
||||
#endif /* HAVE_APPARMOR */
|
||||
&& cs->runchroot == next->runchroot && cs->runcwd == next->runcwd;
|
||||
return ret;
|
||||
}
|
||||
@@ -755,6 +758,16 @@ print_cmndspec_json(struct json_container *jsonc,
|
||||
}
|
||||
#endif /* HAVE_SELINUX */
|
||||
|
||||
#ifdef HAVE_APPARMOR
|
||||
if (cs->apparmor_profile != NULL) {
|
||||
sudo_json_open_array(jsonc, "AppArmor_Spec");
|
||||
value.type = JSON_STRING;
|
||||
value.u.string = cs->apparmor_profile;
|
||||
sudo_json_add_value(jsonc, "apparmor_profile", &value);
|
||||
sudo_json_close_array(jsonc);
|
||||
}
|
||||
#endif /* HAVE_APPARMOR */
|
||||
|
||||
#ifdef HAVE_PRIV_SET
|
||||
/* Print Solaris privs/limitprivs */
|
||||
if (cs->privs != NULL || cs->limitprivs != NULL) {
|
||||
|
@@ -460,6 +460,18 @@ print_cmndspec_ldif(FILE *fp, struct sudoers_parse_tree *parse_tree,
|
||||
}
|
||||
#endif /* HAVE_SELINUX */
|
||||
|
||||
#ifdef HAVE_APPARMOR
|
||||
/* Print AppArmor profile */
|
||||
if (cs->apparmor_profile != NULL) {
|
||||
if (asprintf(&attr_val, "apparmor_profile=%s", cs->apparmor_profile) == -1) {
|
||||
sudo_fatalx(U_("%s: %s"), __func__,
|
||||
U_("unable to allocate memory"));
|
||||
}
|
||||
print_attribute_ldif(fp, "sudoOption", attr_val);
|
||||
free(attr_val);
|
||||
}
|
||||
#endif /* HAVE_APPARMOR */
|
||||
|
||||
#ifdef HAVE_PRIV_SET
|
||||
/* Print Solaris privs/limitprivs */
|
||||
if (cs->privs != NULL || cs->limitprivs != NULL) {
|
||||
|
@@ -976,6 +976,14 @@ cmndspec_equivalent(struct cmndspec *cs1, struct cmndspec *cs2, bool check_negat
|
||||
debug_return_bool(false);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_APPARMOR
|
||||
if (cs1->apparmor_profile != NULL && cs2->apparmor_profile != NULL) {
|
||||
if (strcmp(cs1->apparmor_profile, cs2->apparmor_profile) != 0)
|
||||
debug_return_bool(false);
|
||||
} else if (cs1->apparmor_profile != cs2->apparmor_profile) {
|
||||
debug_return_bool(false);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_PRIV_SET
|
||||
if (cs1->privs != NULL && cs2->privs != NULL) {
|
||||
if (strcmp(cs1->privs, cs2->privs) != 0)
|
||||
|
@@ -667,6 +667,10 @@ struct sudo_defs_types sudo_defs_table[] = {
|
||||
"intercept_type", T_TUPLE,
|
||||
N_("The mechanism used by the intercept and log_subcmds options: %s"),
|
||||
def_data_intercept_type,
|
||||
}, {
|
||||
"apparmor_profile", T_STR,
|
||||
N_("AppArmor profile to use in the new security context: %s"),
|
||||
NULL,
|
||||
}, {
|
||||
NULL, 0, NULL
|
||||
}
|
||||
|
@@ -306,8 +306,10 @@
|
||||
#define def_log_passwords (sudo_defs_table[I_LOG_PASSWORDS].sd_un.flag)
|
||||
#define I_PASSPROMPT_REGEX 152
|
||||
#define def_passprompt_regex (sudo_defs_table[I_PASSPROMPT_REGEX].sd_un.list)
|
||||
#define I_INTERCEPT_TYPE 153
|
||||
#define I_INTERCEPT_TYPE 154
|
||||
#define def_intercept_type (sudo_defs_table[I_INTERCEPT_TYPE].sd_un.tuple)
|
||||
#define I_APPARMOR_PROFILE 153
|
||||
#define def_apparmor_profile (sudo_defs_table[I_APPARMOR_PROFILE].sd_un.str)
|
||||
|
||||
enum def_tuple {
|
||||
never,
|
||||
|
@@ -479,3 +479,6 @@ intercept_type
|
||||
T_TUPLE
|
||||
"The mechanism used by the intercept and log_subcmds options: %s"
|
||||
dso trace
|
||||
apparmor_profile
|
||||
T_STR
|
||||
"AppArmor profile to use in the new security context: %s"
|
@@ -241,6 +241,10 @@ sudoers_format_cmndspec(struct sudo_lbuf *lbuf,
|
||||
if (cs->type != NULL && FIELD_CHANGED(prev_cs, cs, type))
|
||||
sudo_lbuf_append(lbuf, "TYPE=%s ", cs->type);
|
||||
#endif /* HAVE_SELINUX */
|
||||
#ifdef HAVE_APPARMOR
|
||||
if (cs->apparmor_profile != NULL && FIELD_CHANGED(prev_cs, cs, apparmor_profile))
|
||||
sudo_lbuf_append(lbuf, "APPARMOR_PROFILE=%s ", cs->apparmor_profile);
|
||||
#endif /* HAVE_APPARMOR */
|
||||
if (cs->runchroot != NULL && FIELD_CHANGED(prev_cs, cs, runchroot))
|
||||
sudo_lbuf_append(lbuf, "CHROOT=%s ", cs->runchroot);
|
||||
if (cs->runcwd != NULL && FIELD_CHANGED(prev_cs, cs, runcwd))
|
||||
|
@@ -144,6 +144,7 @@ static void alias_error(const char *name, int errnum);
|
||||
%token <tok> CWD /* working directory for command */
|
||||
%token <tok> TYPE /* SELinux type */
|
||||
%token <tok> ROLE /* SELinux role */
|
||||
%token <tok> APPARMOR_PROFILE /* AppArmor profile */
|
||||
%token <tok> PRIVS /* Solaris privileges */
|
||||
%token <tok> LIMITPRIVS /* Solaris limit privileges */
|
||||
%token <tok> CMND_TIMEOUT /* command timeout */
|
||||
@@ -182,6 +183,7 @@ static void alias_error(const char *name, int errnum);
|
||||
%type <string> chrootspec
|
||||
%type <string> rolespec
|
||||
%type <string> typespec
|
||||
%type <string> apparmor_profilespec
|
||||
%type <string> privsspec
|
||||
%type <string> limitprivsspec
|
||||
%type <string> timeoutspec
|
||||
@@ -534,6 +536,10 @@ cmndspec : runasspec options cmndtag digcmnd {
|
||||
cs->type = $2.type;
|
||||
parser_leak_remove(LEAK_PTR, $2.type);
|
||||
#endif
|
||||
#ifdef HAVE_APPARMOR
|
||||
cs->apparmor_profile = $2.apparmor_profile;
|
||||
parser_leak_remove(LEAK_PTR, $2.apparmor_profile);
|
||||
#endif
|
||||
#ifdef HAVE_PRIV_SET
|
||||
cs->privs = $2.privs;
|
||||
parser_leak_remove(LEAK_PTR, $2.privs);
|
||||
@@ -688,6 +694,11 @@ typespec : TYPE '=' WORD {
|
||||
}
|
||||
;
|
||||
|
||||
apparmor_profilespec : APPARMOR_PROFILE '=' WORD {
|
||||
$$ = $3;
|
||||
}
|
||||
;
|
||||
|
||||
privsspec : PRIVS '=' WORD {
|
||||
$$ = $3;
|
||||
}
|
||||
@@ -783,6 +794,7 @@ reserved_word : ALL { $$ = "ALL"; }
|
||||
| TYPE { $$ = "TYPE"; }
|
||||
| PRIVS { $$ = "PRIVS"; }
|
||||
| LIMITPRIVS { $$ = "LIMITPRIVS"; }
|
||||
| APPARMOR_PROFILE { $$ = "APPARMOR_PROFILE"; }
|
||||
;
|
||||
|
||||
reserved_alias : reserved_word {
|
||||
@@ -846,6 +858,13 @@ options : /* empty */ {
|
||||
parser_leak_remove(LEAK_PTR, $$.type);
|
||||
free($$.type);
|
||||
$$.type = $2;
|
||||
#endif
|
||||
}
|
||||
| options apparmor_profilespec {
|
||||
#ifdef HAVE_APPARMOR
|
||||
parser_leak_remove(LEAK_PTR, $$.apparmor_profile);
|
||||
free($$.apparmor_profile);
|
||||
$$.apparmor_profile = $2;
|
||||
#endif
|
||||
}
|
||||
| options privsspec {
|
||||
|
@@ -254,6 +254,24 @@ apply_cmndspec(struct cmndspec *cs)
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_SELINUX */
|
||||
#ifdef HAVE_APPARMOR
|
||||
/* Set AppArmor profile, if specified */
|
||||
if (cs->apparmor_profile != NULL) {
|
||||
user_apparmor_profile = strdup(cs->apparmor_profile);
|
||||
if (user_apparmor_profile == NULL) {
|
||||
sudo_warnx(U_("%s: %s"), __func__,
|
||||
U_("unable to allocate memory"));
|
||||
debug_return_bool(false);
|
||||
}
|
||||
} else {
|
||||
user_apparmor_profile = def_apparmor_profile;
|
||||
def_apparmor_profile = NULL;
|
||||
}
|
||||
if (user_apparmor_profile != NULL) {
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
||||
"user_apparmor_profile -> %s", user_apparmor_profile);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_PRIV_SET
|
||||
/* Set Solaris privilege sets */
|
||||
if (runas_privs == NULL) {
|
||||
@@ -525,6 +543,10 @@ new_long_entry(struct cmndspec *cs, struct cmndspec *prev_cs)
|
||||
if (cs->type && (!prev_cs->type || strcmp(cs->type, prev_cs->type) != 0))
|
||||
debug_return_bool(true);
|
||||
#endif /* HAVE_SELINUX */
|
||||
#ifdef HAVE_APPARMOR
|
||||
if (cs->apparmor_profile && (!prev_cs->apparmor_profile || strcmp(cs->apparmor_profile, prev_cs->apparmor_profile) != 0))
|
||||
debug_return_bool(true);
|
||||
#endif /* HAVE_APPARMOR */
|
||||
if (cs->runchroot && (!prev_cs->runchroot || strcmp(cs->runchroot, prev_cs->runchroot) != 0))
|
||||
debug_return_bool(true);
|
||||
if (cs->runcwd && (!prev_cs->runcwd || strcmp(cs->runcwd, prev_cs->runcwd) != 0))
|
||||
|
@@ -149,6 +149,9 @@ struct command_options {
|
||||
#ifdef HAVE_SELINUX
|
||||
char *role, *type; /* SELinux role and type */
|
||||
#endif
|
||||
#ifdef HAVE_APPARMOR
|
||||
char *apparmor_profile; /* AppArmor profile */
|
||||
#endif
|
||||
#ifdef HAVE_PRIV_SET
|
||||
char *privs, *limitprivs; /* Solaris privilege sets */
|
||||
#endif
|
||||
@@ -233,6 +236,9 @@ struct cmndspec {
|
||||
#ifdef HAVE_SELINUX
|
||||
char *role, *type; /* SELinux role and type */
|
||||
#endif
|
||||
#ifdef HAVE_APPARMOR
|
||||
char *apparmor_profile; /* AppArmor profile */
|
||||
#endif
|
||||
#ifdef HAVE_PRIV_SET
|
||||
char *privs, *limitprivs; /* Solaris privilege sets */
|
||||
#endif
|
||||
|
@@ -328,6 +328,16 @@ sudoers_policy_deserialize_info(void *v, struct defaults_list *defaults)
|
||||
continue;
|
||||
}
|
||||
#endif /* HAVE_SELINUX */
|
||||
#ifdef HAVE_APPARMOR
|
||||
if (MATCHES(*cur, "apparmor_profile=")) {
|
||||
CHECK(*cur, "apparmor_profile=");
|
||||
free(user_apparmor_profile);
|
||||
user_apparmor_profile = strdup(*cur + sizeof("apparmor_profile=") - 1);
|
||||
if (user_apparmor_profile == NULL)
|
||||
goto oom;
|
||||
continue;
|
||||
}
|
||||
#endif /* HAVE_APPARMOR */
|
||||
#ifdef HAVE_BSD_AUTH_H
|
||||
if (MATCHES(*cur, "bsdauth_type=")) {
|
||||
CHECK(*cur, "bsdauth_type=");
|
||||
@@ -957,6 +967,12 @@ sudoers_policy_store_result(bool accepted, char *argv[], char *envp[],
|
||||
goto oom;
|
||||
}
|
||||
#endif /* HAVE_SELINUX */
|
||||
#ifdef HAVE_APPARMOR
|
||||
if (user_apparmor_profile != NULL) {
|
||||
if ((command_info[info_len++] = sudo_new_key_val("apparmor_profile", user_apparmor_profile)) == NULL)
|
||||
goto oom;
|
||||
}
|
||||
#endif /* HAVE_APPARMOR */
|
||||
#ifdef HAVE_PRIV_SET
|
||||
if (runas_privs != NULL) {
|
||||
if ((command_info[info_len++] = sudo_new_key_val("runas_privs", runas_privs)) == NULL)
|
||||
|
@@ -30,6 +30,7 @@
|
||||
"runas_limitprivs"
|
||||
"selinux_role"
|
||||
"selinux_type"
|
||||
"apparmor_profile"
|
||||
"bsdauth_type"
|
||||
"network_addrs"
|
||||
"max_groups"
|
||||
|
@@ -55,6 +55,7 @@
|
||||
"NOTAFTER"
|
||||
"ROLE"
|
||||
"TYPE"
|
||||
"APPARMOR_PROFILE"
|
||||
"PRIVS"
|
||||
"LIMITPRIVS"
|
||||
|
||||
@@ -127,6 +128,7 @@
|
||||
"env_keep"
|
||||
"role"
|
||||
"type"
|
||||
"apparmor_profile"
|
||||
"env_file"
|
||||
"restricted_env_file"
|
||||
"sudoers_locale"
|
||||
|
@@ -1825,6 +1825,9 @@ sudo_user_free(void)
|
||||
free(user_role);
|
||||
free(user_type);
|
||||
#endif
|
||||
#ifdef HAVE_APPARMOR
|
||||
free(user_apparmor_profile);
|
||||
#endif
|
||||
#ifdef HAVE_PRIV_SET
|
||||
free(runas_privs);
|
||||
free(runas_limitprivs);
|
||||
|
@@ -111,6 +111,9 @@ struct sudo_user {
|
||||
char *role;
|
||||
char *type;
|
||||
#endif
|
||||
#ifdef HAVE_APPARMOR
|
||||
char *apparmor_profile;
|
||||
#endif
|
||||
#ifdef HAVE_PRIV_SET
|
||||
char *privs;
|
||||
char *limitprivs;
|
||||
@@ -248,6 +251,7 @@ struct sudo_user {
|
||||
#define runas_gr (sudo_user._runas_gr)
|
||||
#define user_role (sudo_user.role)
|
||||
#define user_type (sudo_user.type)
|
||||
#define user_apparmor_profile (sudo_user.apparmor_profile)
|
||||
#define user_closefrom (sudo_user.closefrom)
|
||||
#define runas_privs (sudo_user.privs)
|
||||
#define runas_limitprivs (sudo_user.limitprivs)
|
||||
|
@@ -679,6 +679,14 @@ ALL {
|
||||
goto got_alias;
|
||||
#endif
|
||||
}
|
||||
<INITIAL>APPARMOR_PROFILE {
|
||||
#ifdef HAVE_APPARMOR
|
||||
LEXTRACE("APPARMOR_PROFILE ");
|
||||
return APPARMOR_PROFILE;
|
||||
#else
|
||||
goto got_alias;
|
||||
#endif
|
||||
}
|
||||
<INITIAL>PRIVS {
|
||||
#ifdef HAVE_PRIV_SET
|
||||
LEXTRACE("PRIVS ");
|
||||
|
@@ -115,7 +115,7 @@ sub mkdep {
|
||||
# Expand some configure bits
|
||||
$makefile =~ s:\@DEV\@::g;
|
||||
$makefile =~ s:\@COMMON_OBJS\@:aix.lo event_poll.lo event_select.lo:;
|
||||
$makefile =~ s:\@SUDO_OBJS\@:intercept.pb-c.o openbsd.o preload.o selinux.o sesh.o solaris.o:;
|
||||
$makefile =~ s:\@SUDO_OBJS\@:intercept.pb-c.o openbsd.o preload.o apparmor.o selinux.o sesh.o solaris.o:;
|
||||
$makefile =~ s:\@SUDOERS_OBJS\@:bsm_audit.lo linux_audit.lo ldap.lo ldap_util.lo ldap_conf.lo solaris_audit.lo sssd.lo:;
|
||||
# XXX - fill in AUTH_OBJS from contents of the auth dir instead
|
||||
$makefile =~ s:\@AUTH_OBJS\@:afs.lo aix_auth.lo bsdauth.lo dce.lo fwtk.lo getspwuid.lo kerb5.lo pam.lo passwd.lo rfc1938.lo secureware.lo securid5.lo sia.lo:;
|
||||
|
@@ -269,6 +269,23 @@ case "$osversion" in
|
||||
make_opts="${make_opts}${make_opts+ }"'docdir=$(datarootdir)/doc/packages/$(PACKAGE_TARNAME)'
|
||||
;;
|
||||
deb*|ubu*)
|
||||
# AppArmor is enabled by default starting in
|
||||
# Debian: Debian 10 (Buster)
|
||||
# Ubuntu: Ubuntu 12.04 (Precise Pangolin)
|
||||
osmajor=`sed -n -e 's/^VERSION_ID=\"\([0-9]*\).*$/\1/p' /etc/os-release`
|
||||
case "$osversion" in
|
||||
deb*)
|
||||
if [ -z $osmajor ] || [ $osmajor -ge 10 ]; then
|
||||
with_apparmor=true
|
||||
fi
|
||||
;;
|
||||
ubu*)
|
||||
if [ -z $osmajor ] || [ $osmajor -ge 14 ]; then
|
||||
with_apparmor=true
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Encrypted remote I/O log support.
|
||||
with_openssl=true
|
||||
# Python plugins
|
||||
@@ -295,6 +312,9 @@ case "$osversion" in
|
||||
configure_opts="${configure_opts}${configure_opts+$tab}--with-sssd-lib=/usr/lib/$MULTIARCH"
|
||||
fi
|
||||
fi
|
||||
if [ X"$with_apparmor" = X"true" ]; then
|
||||
configure_opts="${configure_opts}${configure_opts+$tab}--with-apparmor"
|
||||
fi
|
||||
configure_opts="--prefix=/usr
|
||||
--with-all-insults
|
||||
--with-pam
|
||||
@@ -311,7 +331,6 @@ case "$osversion" in
|
||||
--with-sendmail=/usr/sbin/sendmail
|
||||
--mandir=/usr/share/man
|
||||
--libexecdir=/usr/lib
|
||||
--with-selinux
|
||||
--with-linux-audit
|
||||
$configure_opts"
|
||||
# Use correct libaudit dependency
|
||||
|
@@ -378,6 +378,24 @@ sudo_noexec.lo: $(srcdir)/sudo_noexec.c $(incdir)/sudo_compat.h \
|
||||
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/sudo_noexec.c
|
||||
|
||||
# Autogenerated dependencies, do not modify
|
||||
apparmor.o: $(srcdir)/apparmor.c $(incdir)/compat/stdbool.h \
|
||||
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
||||
$(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
|
||||
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
||||
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
|
||||
$(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
|
||||
$(top_builddir)/pathnames.h
|
||||
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/apparmor.c
|
||||
apparmor.i: $(srcdir)/apparmor.c $(incdir)/compat/stdbool.h \
|
||||
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
||||
$(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
|
||||
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
||||
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
|
||||
$(incdir)/sudo_util.h $(srcdir)/sudo.h $(top_builddir)/config.h \
|
||||
$(top_builddir)/pathnames.h
|
||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||
apparmor.plog: apparmor.i
|
||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/apparmor.c --i-file $< --output-file $@
|
||||
check_net_ifs.o: $(srcdir)/regress/net_ifs/check_net_ifs.c \
|
||||
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
||||
$(incdir)/sudo_util.h $(top_builddir)/config.h
|
||||
|
111
src/apparmor.c
Normal file
111
src/apparmor.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* Copyright (c) 2022 Will Shand <wss2ec@virginia.edu>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifdef HAVE_APPARMOR
|
||||
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <sys/apparmor.h>
|
||||
|
||||
# include "sudo.h"
|
||||
# include "sudo_debug.h"
|
||||
|
||||
/**
|
||||
* @brief Check whether AppArmor is enabled.
|
||||
*
|
||||
* @return 1 if AppArmor is enabled, 0 otherwise.
|
||||
*/
|
||||
int
|
||||
apparmor_is_enabled(void)
|
||||
{
|
||||
int ret;
|
||||
FILE *fd;
|
||||
debug_decl(apparmor_is_enabled, SUDO_DEBUG_APPARMOR);
|
||||
|
||||
/* Check whether AppArmor is enabled by reading
|
||||
* /sys/module/apparmor/parameters/enabled
|
||||
*
|
||||
* When this file exists and its contents are equal to "Y", AppArmor
|
||||
* is enabled. This is a little more reliable than using
|
||||
* aa_is_enabled(2), which performs an additional check on securityfs
|
||||
* that will fail in settings where securityfs isn't available
|
||||
* (e.g. inside a container).
|
||||
*/
|
||||
|
||||
fd = fopen("/sys/module/apparmor/parameters/enabled", "r");
|
||||
if (fd == NULL)
|
||||
debug_return_int(0);
|
||||
|
||||
ret = (fgetc(fd) == 'Y');
|
||||
|
||||
fclose(fd);
|
||||
debug_return_int(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prepare to transition into a new AppArmor profile.
|
||||
*
|
||||
* @param new_profile The AppArmor profile to transition into on the
|
||||
* next exec.
|
||||
*
|
||||
* @return 0 on success, and a nonzero value on failure.
|
||||
*/
|
||||
int
|
||||
apparmor_prepare(const char *new_profile)
|
||||
{
|
||||
int ret;
|
||||
char *mode, *old_profile;
|
||||
debug_decl(apparmor_prepare, SUDO_DEBUG_APPARMOR);
|
||||
|
||||
/* Determine the current AppArmor confinement status */
|
||||
if ((ret = aa_getcon(&old_profile, &mode)) == -1) {
|
||||
sudo_warn("%s", U_("failed to determine AppArmor confinement"));
|
||||
old_profile = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Tell AppArmor to transition into the new profile on the
|
||||
* next exec */
|
||||
if ((ret = aa_change_onexec(new_profile)) != 0) {
|
||||
sudo_warn(U_("unable to change AppArmor profile to %s"), new_profile);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (mode == NULL)
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO,
|
||||
"%s: changing AppArmor profile: %s -> %s", __func__,
|
||||
old_profile, new_profile ? new_profile : "?"
|
||||
);
|
||||
else
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO,
|
||||
"%s: changing AppArmor profile: %s (%s) -> %s", __func__,
|
||||
old_profile, mode, new_profile ? new_profile : "?"
|
||||
);
|
||||
|
||||
done:
|
||||
/* The profile string returned by aa_getcon must be free'd, while the
|
||||
* mode string must _not_ be free'd */
|
||||
if (old_profile != NULL)
|
||||
free(old_profile);
|
||||
|
||||
debug_return_int(ret);
|
||||
}
|
||||
|
||||
#endif /* HAVE_APPARMOR */
|
@@ -83,6 +83,7 @@ static struct sudo_settings sudo_settings[] = {
|
||||
{ "askpass" },
|
||||
{ "intercept_setid" },
|
||||
{ "intercept_ptrace" },
|
||||
{ "apparmor_profile" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
12
src/sudo.c
12
src/sudo.c
@@ -689,6 +689,9 @@ command_info_to_details(char * const info[], struct command_details *details)
|
||||
for (i = 0; info[i] != NULL; i++) {
|
||||
sudo_debug_printf(SUDO_DEBUG_INFO, " %d: %s", i, info[i]);
|
||||
switch (info[i][0]) {
|
||||
case 'a':
|
||||
SET_STRING("apparmor_profile=", apparmor_profile);
|
||||
break;
|
||||
case 'c':
|
||||
SET_STRING("chroot=", chroot)
|
||||
SET_STRING("command=", command)
|
||||
@@ -895,6 +898,15 @@ command_info_to_details(char * const info[], struct command_details *details)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_APPARMOR
|
||||
if (details->apparmor_profile != NULL && apparmor_is_enabled()) {
|
||||
i = apparmor_prepare(details->apparmor_profile);
|
||||
if (i != 0)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
||||
|
@@ -104,6 +104,7 @@
|
||||
#define ARG_ASKPASS 25
|
||||
#define ARG_INTERCEPT_SETID 26
|
||||
#define ARG_INTERCEPT_PTRACE 27
|
||||
#define ARG_APPARMOR_PROFILE 28
|
||||
|
||||
/*
|
||||
* Flags for tgetpass()
|
||||
@@ -199,6 +200,7 @@ struct command_details {
|
||||
const char *chroot;
|
||||
const char *selinux_role;
|
||||
const char *selinux_type;
|
||||
const char *apparmor_profile;
|
||||
const char *utmp_user;
|
||||
const char *tty;
|
||||
char **argv;
|
||||
@@ -286,6 +288,10 @@ int selinux_setexeccon(void);
|
||||
void selinux_execve(int fd, const char *path, char *const argv[],
|
||||
char *envp[], int flags);
|
||||
|
||||
/* apparmor.c */
|
||||
int apparmor_is_enabled(void);
|
||||
int apparmor_prepare(const char* new_profile);
|
||||
|
||||
/* solaris.c */
|
||||
void set_project(struct passwd *);
|
||||
int os_init_solaris(int argc, char *argv[], char *envp[]);
|
||||
|
Reference in New Issue
Block a user