On Thu, Apr 4, 2019 at 8:37 AM Joshua Brindle <joshua.brindle@xxxxxxxxxxxxxxx> wrote: > > It seems validatetrans support was never added to libselinux, despite being added to > selinuxfs in kernel version 4.5 > > Signed-off-by: Joshua Brindle <joshua.brindle@xxxxxxxxxxxxxxx> > --- > libselinux/include/selinux/selinux.h | 13 +++ > libselinux/man/man3/security_compute_av.3 | 13 ++- > libselinux/man/man3/security_validatetrans.c | 1 + > .../man/man3/security_validatetrans_raw.c | 1 + > libselinux/src/selinux_internal.h | 2 + > libselinux/src/validatetrans.c | 80 +++++++++++++++++++ > 6 files changed, 109 insertions(+), 1 deletion(-) > create mode 100644 libselinux/man/man3/security_validatetrans.c > create mode 100644 libselinux/man/man3/security_validatetrans_raw.c > create mode 100644 libselinux/src/validatetrans.c > > diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h > index a34d54fc..948028ea 100644 > --- a/libselinux/include/selinux/selinux.h > +++ b/libselinux/include/selinux/selinux.h > @@ -255,6 +255,19 @@ extern int security_compute_user_raw(const char * scon, > const char *username, > char *** con); > > +/* Validate a transition. This determines whether a transition from scon to newcon > + using tcon as the target for object class tclass is valid in the loaded policy. > + This checks against the mlsvalidatetrans and validatetrans constraints in the loaded policy. > + Returns 0 if allowed, -EPERM if denied, and -1 if an error occured */ > +extern int security_validatetrans(const char *scon, > + const char *tcon, > + security_class_t tclass, > + const char *newcon); > +extern int security_validatetrans_raw(const char *scon, > + const char *tcon, > + security_class_t tclass, > + const char *newcon); > + > /* Load a policy configuration. */ > extern int security_load_policy(void *data, size_t len); > > diff --git a/libselinux/man/man3/security_compute_av.3 b/libselinux/man/man3/security_compute_av.3 > index 2aade5fe..e03960bc 100644 > --- a/libselinux/man/man3/security_compute_av.3 > +++ b/libselinux/man/man3/security_compute_av.3 > @@ -1,7 +1,7 @@ > .TH "security_compute_av" "3" "1 January 2004" "russell@xxxxxxxxxxxx" "SELinux API documentation" > .SH "NAME" > security_compute_av, security_compute_av_flags, security_compute_create, security_compute_create_name, security_compute_relabel, > -security_compute_member, security_compute_user, security_get_initial_context \- query > +security_compute_member, security_compute_user, security_validatetrans, security_get_initial_context \- query > the SELinux policy database in the kernel > . > .SH "SYNOPSIS" > @@ -35,6 +35,10 @@ the SELinux policy database in the kernel > .sp > .BI "int security_compute_user_raw(char *" scon ", const char *" username ", char ***" con ); > .sp > +.BI "int security_validatetrans(char *" scon ", const char *" tcon ", security_class_t "tclass ", char *" newcon ); > +.sp > +.BI "int security_validatetrans_raw(char *" scon ", const char *" tcon ", security_class_t "tclass ", char *" newcon ); > +.sp > .BI "int security_get_initial_context(const char *" name ", char **" con ); > .sp > .BI "int security_get_initial_context_raw(const char *" name ", char **" con ); > @@ -100,6 +104,12 @@ is used to determine the set of user contexts that can be reached from a > source context. It is mainly used by > .BR get_ordered_context_list (). > > +.BR security_validatetrans () > +is used to determine if a transition from scon to newcon using tcon as the object > +is valid for object class tclass. This checks against the mlsvalidatetrans and > +validatetrans constraints in the loaded policy. Returns 0 if allowed, -EPERM if denied, > +and -1 if an error occured > + > .BR security_get_initial_context () > is used to get the context of a kernel initial security identifier specified by > .I name > @@ -111,6 +121,7 @@ is used to get the context of a kernel initial security identifier specified by > .BR \%security_compute_relabel_raw (), > .BR \%security_compute_member_raw (), > .BR \%security_compute_user_raw () > +.BR \%security_validatetrans_raw () > and > .BR \%security_get_initial_context_raw () > behave identically to their non-raw counterparts but do not perform context > diff --git a/libselinux/man/man3/security_validatetrans.c b/libselinux/man/man3/security_validatetrans.c > new file mode 100644 > index 00000000..a60bca4d > --- /dev/null > +++ b/libselinux/man/man3/security_validatetrans.c > @@ -0,0 +1 @@ > +.so man3/security_compute_av.3 > diff --git a/libselinux/man/man3/security_validatetrans_raw.c b/libselinux/man/man3/security_validatetrans_raw.c > new file mode 100644 > index 00000000..a60bca4d > --- /dev/null > +++ b/libselinux/man/man3/security_validatetrans_raw.c > @@ -0,0 +1 @@ > +.so man3/security_compute_av.3 > diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h > index 70b5025d..acd59c7c 100644 > --- a/libselinux/src/selinux_internal.h > +++ b/libselinux/src/selinux_internal.h > @@ -29,6 +29,8 @@ hidden_proto(selinux_mkload_policy) > hidden_proto(security_compute_create_name_raw) > hidden_proto(security_compute_member_raw) > hidden_proto(security_compute_relabel_raw) > + hidden_proto(security_validatetrans) > + hidden_proto(security_validatetrans_raw) > hidden_proto(is_selinux_enabled) > hidden_proto(is_selinux_mls_enabled) > hidden_proto(freecon) > diff --git a/libselinux/src/validatetrans.c b/libselinux/src/validatetrans.c > new file mode 100644 > index 00000000..86bfaa30 > --- /dev/null > +++ b/libselinux/src/validatetrans.c > @@ -0,0 +1,80 @@ > +#include <unistd.h> > +#include <sys/types.h> > +#include <fcntl.h> > +#include <stdlib.h> > +#include <stdio.h> > +#include <errno.h> > +#include <string.h> > +#include <limits.h> > +#include "selinux_internal.h" > +#include "policy.h" > +#include "mapping.h" > + > +int security_validatetrans_raw(const char *scon, > + const char *tcon, > + security_class_t tclass, > + const char *newcon) > +{ > + char path[PATH_MAX]; > + char *buf; > + size_t size; > + int fd, ret; > + > + if (!selinux_mnt) { > + errno = ENOENT; > + return -1; > + } > + > + snprintf(path, sizeof path, "%s/validatetrans", selinux_mnt); > + fd = open(path, O_RDWR | O_CLOEXEC); > + if (fd < 0) > + return -1; > + > + size = selinux_page_size; > + buf = malloc(size); > + if (!buf) { > + ret = -1; > + goto out; > + } > + snprintf(buf, size, "%s %s %hu %s", scon, tcon, unmap_class(tclass), newcon); Shouldn't we be checking both snprintf's for truncation? I see things like selinux_status_open() not doing it, also it doesn't use selinux_page_size but calls sysconf() directly, so that might not be the best example. I just wonder if we're glossing over truncation bugs that might be hard to debug if they ever crop up without explicit errors. > + > + ret = write(fd, buf, strlen(buf)); > + free(buf); > +out: > + close(fd); > + return ret; > +} > + > +hidden_def(security_validatetrans_raw) > + > +int security_validatetrans(const char *scon, > + const char *tcon, > + security_class_t tclass, > + const char *newcon) > +{ > + int ret = -1; > + char *rscon = NULL; > + char *rtcon = NULL; > + char *rnewcon = NULL; > + > + if (selinux_trans_to_raw_context(scon, &rscon)) { > + goto out; > + } > + > + if (selinux_trans_to_raw_context(tcon, &rtcon)) { > + goto out; > + } > + > + if (selinux_trans_to_raw_context(newcon, &rnewcon)) { > + goto out; > + } > + > + ret = security_validatetrans_raw(rscon, rtcon, tclass, rnewcon); > + > +out: > + freecon(rnewcon); > + freecon(rtcon); > + freecon(rscon); > + > + return ret; > +} > -- > 2.17.2 > $ git am ~/Downloads/\[PATCH\]\ Add\ security_validatetrans\ support.eml Applying: Add security_validatetrans support .git/rebase-apply/patch:68: trailing whitespace. validatetrans constraints in the loaded policy. Returns 0 if allowed, -EPERM if denied, warning: 1 line adds whitespace errors. Other then my question and trailing whitespace, overall LGTM. Builds and passes.