Commit 447fdc9d authored by Lukas Braun's avatar Lukas Braun Committed by Simon Ruderich
Browse files

slsm: split mode field into mode and flags

Rename SLSM_ALLOW_* to SLSM_MODE_*.
Sysfs interface flags have been altered as follows:
  'p' is now path (previously 'f')
  'f' is now flags (new, inherit is f=1)
  'm' is now mode (previously 'p')
parent abf5ea47
......@@ -88,7 +88,7 @@ static int passt_bprm_set_creds(struct linux_binprm *bprm) {
char *buffer = NULL;
const char *name = NULL;
int error = 0;
unsigned mode;
struct slsm_perms perms;
if (bprm->cred_prepared)
return 0;
......@@ -101,9 +101,9 @@ static int passt_bprm_set_creds(struct linux_binprm *bprm) {
goto audit;
}
mode = slsm_query_mode(name, pt->label);
if (mode & SLSM_ALLOW_EXEC) {
if (!pt->inherit && !(mode & SLSM_INHERIT)) {
perms = slsm_query_perms(name, pt->label);
if (perms.mode & SLSM_MODE_X) {
if (!pt->inherit && !(perms.flags & SLSM_FLAG_INHERIT)) {
// TODO: cache labels
char *old_label = pt->label;
char *new_label = kstrdup(name, GFP_KERNEL);
......@@ -153,11 +153,11 @@ static int passt_bprm_secureexec(struct linux_binprm *bprm) {
static int passt_path_common(const struct path *path, const struct cred *cred,
unsigned mode_want) {
struct slsm_perms perms_want) {
struct passt_task *pt = cred->security;
char *buffer = NULL;
const char *name = NULL;
unsigned mode;
struct slsm_perms perms;
int error = 0;
name = passt_get_path(path, &buffer);
......@@ -166,10 +166,10 @@ static int passt_path_common(const struct path *path, const struct cred *cred,
goto cleanup;
}
mode = slsm_query_mode(name, pt->label);
if ((mode & mode_want) != mode_want) {
perms = slsm_query_perms(name, pt->label);
if (!slsm_perms_mode_grant(perms, perms_want)) {
printk(KERN_INFO "DENIED: %s wants %o on %s, has %o\n",
pt->label, mode_want, name, mode);
pt->label, perms_want.mode, name, perms.mode);
error = -EACCES;
}
......@@ -180,16 +180,16 @@ cleanup:
static int passt_file_open(struct file *file, const struct cred *cred) {
unsigned mode_want = 0;
struct slsm_perms perms_want = { .mode = 0, .flags = 0 };
if (current->in_execve)
/* handled by bprm hooks */
return 0;
/* TODO: do we have to handle O_CREAT here? */
mode_want |= (file->f_mode & FMODE_READ) ? SLSM_ALLOW_READ : 0;
mode_want |= (file->f_mode & FMODE_WRITE) ? SLSM_ALLOW_WRITE : 0;
return passt_path_common(&file->f_path, cred, mode_want);
perms_want.mode |= (file->f_mode & FMODE_READ) ? SLSM_MODE_R : 0;
perms_want.mode |= (file->f_mode & FMODE_WRITE) ? SLSM_MODE_W : 0;
return passt_path_common(&file->f_path, cred, perms_want);
}
static int passt_path_link(struct dentry *old_dentry, struct path *new_dir,
......@@ -200,11 +200,11 @@ static int passt_path_link(struct dentry *old_dentry, struct path *new_dir,
/* TODO: is the mountpoint always the same for new_ and old_dentry?
* bindmounts etc. */
struct path target = { new_dir->mnt, old_dentry };
unsigned would_get;
struct slsm_perms would_get;
char *buffer = NULL;
const char *link_name = NULL;
if (passt_path_common(new_dir, current->cred, SLSM_ALLOW_WRITE))
if (passt_path_common(new_dir, current->cred, SLSM_PERMS_W))
return -EACCES;
link_name = passt_get_path(&link, &buffer);
......@@ -213,7 +213,7 @@ static int passt_path_link(struct dentry *old_dentry, struct path *new_dir,
return PTR_ERR(link_name);
}
would_get = slsm_query_mode(link_name, pt->label);
would_get = slsm_query_perms(link_name, pt->label);
kfree(buffer);
return passt_path_common(&target, current->cred, would_get);
}
......@@ -222,41 +222,41 @@ static int passt_path_symlink(struct path *dir, struct dentry *dentry,
const char *old_name) {
/* Symlinks are always followed so there's no need to verify the
* target here. */
return passt_path_common(dir, current->cred, SLSM_ALLOW_WRITE);
return passt_path_common(dir, current->cred, SLSM_PERMS_W);
}
static int passt_path_unlink(struct path *dir, struct dentry *dentry) {
return passt_path_common(dir, current->cred, SLSM_ALLOW_WRITE);
return passt_path_common(dir, current->cred, SLSM_PERMS_W);
}
static int passt_path_rename(struct path *old_dir, struct dentry *old_dentry,
struct path *new_dir, struct dentry *new_dentry) {
if (passt_path_common(old_dir, current->cred, SLSM_ALLOW_WRITE) ||
passt_path_common(new_dir, current->cred, SLSM_ALLOW_WRITE))
if (passt_path_common(old_dir, current->cred, SLSM_PERMS_W) ||
passt_path_common(new_dir, current->cred, SLSM_PERMS_W))
return -EACCES;
return 0;
}
static int passt_path_mkdir(struct path *dir, struct dentry *dentry,
umode_t mode) {
return passt_path_common(dir, current->cred, SLSM_ALLOW_WRITE);
return passt_path_common(dir, current->cred, SLSM_PERMS_W);
}
static int passt_path_rmdir(struct path *dir, struct dentry *dentry) {
return passt_path_common(dir, current->cred, SLSM_ALLOW_WRITE);
return passt_path_common(dir, current->cred, SLSM_PERMS_W);
}
static int passt_path_mknod(struct path *dir, struct dentry *dentry,
umode_t mode, unsigned int dev) {
return passt_path_common(dir, current->cred, SLSM_ALLOW_WRITE);
return passt_path_common(dir, current->cred, SLSM_PERMS_W);
}
static int passt_path_chmod(struct path *path, umode_t mode) {
return passt_path_common(path, current->cred, SLSM_ALLOW_WRITE);
return passt_path_common(path, current->cred, SLSM_PERMS_W);
}
static int passt_path_chown(struct path *path, kuid_t uid, kgid_t gid) {
return passt_path_common(path, current->cred, SLSM_ALLOW_WRITE);
return passt_path_common(path, current->cred, SLSM_PERMS_W);
}
......@@ -266,8 +266,7 @@ static int passt_unix_common(struct sock *other) {
if (!u_other->addr || !u_other->addr->name->sun_path[0])
return 0;
return passt_path_common(&u_other->path, current->cred,
SLSM_ALLOW_WRITE | SLSM_ALLOW_READ);
return passt_path_common(&u_other->path, current->cred, SLSM_PERMS_RW);
}
static int passt_unix_stream_connect(struct sock *sock, struct sock *other,
......
......@@ -22,7 +22,7 @@ setup() {
mount -t securityfs securityfs /tmp/slsm-security || exit 1
}
cleanup() {
rules 'f=/' 'p=7' # allow everything
rules 'p=/' 'm=7' # allow everything
umount /tmp/slsm-security
rm -rf /tmp/slsm /tmp/slsm-security
}
......@@ -53,28 +53,28 @@ TOUCH="$(absolute_path touch)"
test_expect_success 'disallow all access to /' "
test_when_finished cleanup && setup &&
\
rules f=/ a=$CAT p=0 &&
rules p=/ a=$CAT m=0 &&
! $CAT /dev/null # test_must_fail does not work here as the binary can't start
"
test_expect_success 'disallow read access to /' "
test_when_finished cleanup && setup &&
\
rules f=/ a=$CAT p=3 &&
rules p=/ a=$CAT m=3 &&
! $CAT /dev/null # test_must_fail does not work here as the binary can't start
"
test_expect_success 'disallow write access to /' "
test_when_finished cleanup && setup &&
touch /tmp/slsm/test-me &&
\
rules f=/ a=$RM p=5 '' \
f=/ a=$LN p=5 &&
rules p=/ a=$RM m=5 '' \
p=/ a=$LN m=5 &&
test_must_fail $RM /tmp/slsm/test-me &&
test_must_fail $LN -s y /tmp/slsm/x
"
test_expect_success 'disallow exec access to /' "
test_when_finished cleanup && setup &&
\
rules f=/ a=$PERL p=6 &&
rules p=/ a=$PERL m=6 &&
test_must_fail $PERL -e 'system(\"true\") == 0 or exit 1'
"
......@@ -82,7 +82,7 @@ test_expect_success 'disallow all access to /tmp/slsm' "
test_when_finished cleanup && setup &&
touch /tmp/slsm/test-me &&
\
rules f=/tmp/slsm a=$CAT p=0 &&
rules p=/tmp/slsm a=$CAT m=0 &&
test_must_fail $CAT /tmp/slsm/test-me &&
$CAT /dev/null
"
......@@ -90,15 +90,15 @@ test_expect_success 'disallow read access to /tmp/slsm' "
test_when_finished cleanup && setup &&
touch /tmp/slsm/test-me &&
\
rules f=/tmp/slsm a=$CAT p=3 &&
rules p=/tmp/slsm a=$CAT m=3 &&
test_must_fail $CAT /tmp/slsm/test-me &&
$CAT /dev/null
"
test_expect_success 'disallow write access to /tmp/slsm' "
test_when_finished cleanup && setup &&
\
rules f=/tmp/slsm a=$TOUCH p=5 '' \
f=/tmp/slsm a=$LN p=5 &&
rules p=/tmp/slsm a=$TOUCH m=5 '' \
p=/tmp/slsm a=$LN m=5 &&
test_must_fail $TOUCH /tmp/slsm/test-me &&
test_must_fail $LN -s y /tmp/slsm/x &&
$TOUCH /var/tmp/test-me &&
......@@ -116,15 +116,15 @@ test_expect_success 'disallow exec access to /tmp/slsm' "
/tmp/slsm/test-me2 >actual &&
test_cmp expected actual &&
\
rules f=/tmp/slsm a=$BASH p=6 &&
rules p=/tmp/slsm a=$BASH m=6 &&
test_must_fail $BASH /tmp/slsm/test-me
"
test_expect_success 'no circumvention via hardlinks' "
test_when_finished cleanup && setup &&
touch /tmp/slsm/test-me &&
\
rules f=/tmp/slsm/test-me p=4 '' \
f=/tmp/slsm/test-me2 p=0 &&
rules p=/tmp/slsm/test-me m=4 '' \
p=/tmp/slsm/test-me2 m=0 &&
ln /tmp/slsm/test-me /tmp/slsm/test-me2 &&
test_must_fail ln /tmp/slsm/test-me /tmp/slsm/test-me3
"
......@@ -134,7 +134,7 @@ test_expect_success 'disallow all access to file' "
echo test-me >/tmp/slsm/test-me &&
echo test-me2 >/tmp/slsm/test-me2 &&
\
rules f=/tmp/slsm/test-me p=0 &&
rules p=/tmp/slsm/test-me m=0 &&
test_must_fail cat /tmp/slsm/test-me &&
test_must_fail sh -c 'echo >/tmp/slsm/test-me' &&
rm /tmp/slsm/test-me &&
......@@ -146,8 +146,8 @@ test_expect_success 'disallow delete of file' "
test_when_finished cleanup && setup &&
echo test-me >/tmp/slsm/test-me &&
\
rules f=/tmp/slsm p=0 '' \
f=/tmp/slsm/test-me p=7 &&
rules p=/tmp/slsm m=0 '' \
p=/tmp/slsm/test-me m=7 &&
test_must_fail rm /tmp/slsm/test-me &&
echo test-me >expected &&
test_cmp expected /tmp/slsm/test-me &&
......@@ -161,33 +161,33 @@ test_expect_success 'last matching rule for a node is used' "
echo test-me >/tmp/slsm/test-me &&
echo test-me2 >/tmp/slsm/test-me2 &&
\
rules f=/tmp/slsm/test-me a=$CAT p=7 '' \
f=/tmp/slsm/test-me a=$CAT p=7 '' \
f=/tmp/slsm/test-me a=$CAT p=7 '' \
f=/tmp/slsm/test-me a=$CAT p=6 '' \
f=/tmp/slsm/test-me a=$CAT p=6 '' \
f=/tmp/slsm/test-me a=$CAT p=6 '' \
f=/tmp/slsm/test-me a=$CAT p=5 '' \
f=/tmp/slsm/test-me a=$CAT p=5 '' \
f=/tmp/slsm/test-me a=$CAT p=5 '' \
f=/tmp/slsm/test-me a=$CAT p=4 '' \
f=/tmp/slsm/test-me a=$CAT p=4 '' \
f=/tmp/slsm/test-me a=$CAT p=4 '' \
f=/tmp/slsm/test-me a=$CAT p=3 '' \
f=/tmp/slsm/test-me a=$CAT p=3 '' \
f=/tmp/slsm/test-me a=$CAT p=3 '' \
f=/tmp/slsm/test-me a=$CAT p=2 '' \
f=/tmp/slsm/test-me a=$CAT p=2 '' \
f=/tmp/slsm/test-me a=$CAT p=2 '' \
f=/tmp/slsm/test-me a=$CAT p=1 '' \
f=/tmp/slsm/test-me a=$CAT p=1 '' \
f=/tmp/slsm/test-me a=$CAT p=1 '' \
f=/tmp/slsm/test-me a=$CAT p=0 '' \
f=/tmp/slsm/test-me a=$CAT p=0 '' \
f=/tmp/slsm/test-me a=$CAT p=0 '' \
f=/tmp/slsm/test-me2 a=$CAT p=0 '' \
f=/tmp/slsm/test-me2 a=$CAT p=2 '' \
f=/tmp/slsm/test-me2 a=$CAT p=4 &&
rules p=/tmp/slsm/test-me a=$CAT m=7 '' \
p=/tmp/slsm/test-me a=$CAT m=7 '' \
p=/tmp/slsm/test-me a=$CAT m=7 '' \
p=/tmp/slsm/test-me a=$CAT m=6 '' \
p=/tmp/slsm/test-me a=$CAT m=6 '' \
p=/tmp/slsm/test-me a=$CAT m=6 '' \
p=/tmp/slsm/test-me a=$CAT m=5 '' \
p=/tmp/slsm/test-me a=$CAT m=5 '' \
p=/tmp/slsm/test-me a=$CAT m=5 '' \
p=/tmp/slsm/test-me a=$CAT m=4 '' \
p=/tmp/slsm/test-me a=$CAT m=4 '' \
p=/tmp/slsm/test-me a=$CAT m=4 '' \
p=/tmp/slsm/test-me a=$CAT m=3 '' \
p=/tmp/slsm/test-me a=$CAT m=3 '' \
p=/tmp/slsm/test-me a=$CAT m=3 '' \
p=/tmp/slsm/test-me a=$CAT m=2 '' \
p=/tmp/slsm/test-me a=$CAT m=2 '' \
p=/tmp/slsm/test-me a=$CAT m=2 '' \
p=/tmp/slsm/test-me a=$CAT m=1 '' \
p=/tmp/slsm/test-me a=$CAT m=1 '' \
p=/tmp/slsm/test-me a=$CAT m=1 '' \
p=/tmp/slsm/test-me a=$CAT m=0 '' \
p=/tmp/slsm/test-me a=$CAT m=0 '' \
p=/tmp/slsm/test-me a=$CAT m=0 '' \
p=/tmp/slsm/test-me2 a=$CAT m=0 '' \
p=/tmp/slsm/test-me2 a=$CAT m=2 '' \
p=/tmp/slsm/test-me2 a=$CAT m=4 &&
test_must_fail $CAT /tmp/slsm/test-me &&
echo test-me2 >expected &&
$CAT /tmp/slsm/test-me2 >actual &&
......@@ -209,14 +209,14 @@ test_expect_success 'most specific path is used' "
done &&
find /tmp/slsm | sort &&
\
rules f=/tmp/slsm p=0 '' \
f=/tmp/slsm/a p=1 '' \
f=/tmp/slsm/a/b p=2 '' \
f=/tmp/slsm/a/b/c p=3 '' \
f=/tmp/slsm/a/b/c/d p=4 '' \
f=/tmp/slsm/a/b/c/d/e p=5 '' \
f=/tmp/slsm/a/b/c/d/e/f p=6 '' \
f=/tmp/slsm/a/b/c/d/e/f/g p=7 &&
rules p=/tmp/slsm m=0 '' \
p=/tmp/slsm/a m=1 '' \
p=/tmp/slsm/a/b m=2 '' \
p=/tmp/slsm/a/b/c m=3 '' \
p=/tmp/slsm/a/b/c/d m=4 '' \
p=/tmp/slsm/a/b/c/d/e m=5 '' \
p=/tmp/slsm/a/b/c/d/e/f m=6 '' \
p=/tmp/slsm/a/b/c/d/e/f/g m=7 &&
\
test_must_fail cat /tmp/slsm/x &&
test_must_fail /tmp/slsm/y &&
......@@ -257,11 +257,11 @@ test_expect_success 'multiple rules per file' "
test_when_finished cleanup && setup &&
echo test-me >/tmp/slsm/test-me &&
\
rules f=/tmp/slsm/test-me a=$CAT p=0 '' \
f=/tmp/slsm/test-me a=$HEAD p=0 '' \
f=/tmp/slsm/test-me a=$TAIL p=0 '' \
f=/tmp/slsm/test-me a=$PERL p=2 '' \
f=/tmp/slsm/test-me a=$BASH p=0 &&
rules p=/tmp/slsm/test-me a=$CAT m=0 '' \
p=/tmp/slsm/test-me a=$HEAD m=0 '' \
p=/tmp/slsm/test-me a=$TAIL m=0 '' \
p=/tmp/slsm/test-me a=$PERL m=2 '' \
p=/tmp/slsm/test-me a=$BASH m=0 &&
test_must_fail $CAT /tmp/slsm/test-me &&
test_must_fail $HEAD /tmp/slsm/test-me &&
test_must_fail $TAIL /tmp/slsm/test-me &&
......@@ -273,11 +273,11 @@ test_expect_success 'multiple rules per file (argument order reversed)' "
test_when_finished cleanup && setup &&
echo test-me >/tmp/slsm/test-me &&
\
rules f=/tmp/slsm/test-me p=0 a=$CAT '' \
f=/tmp/slsm/test-me p=0 a=$HEAD '' \
f=/tmp/slsm/test-me p=0 a=$TAIL '' \
f=/tmp/slsm/test-me p=2 a=$PERL '' \
f=/tmp/slsm/test-me p=0 a=$BASH &&
rules p=/tmp/slsm/test-me m=0 a=$CAT '' \
p=/tmp/slsm/test-me m=0 a=$HEAD '' \
p=/tmp/slsm/test-me m=0 a=$TAIL '' \
p=/tmp/slsm/test-me m=2 a=$PERL '' \
p=/tmp/slsm/test-me m=0 a=$BASH &&
test_must_fail $CAT /tmp/slsm/test-me &&
test_must_fail $HEAD /tmp/slsm/test-me &&
test_must_fail $TAIL /tmp/slsm/test-me &&
......@@ -295,15 +295,15 @@ test_expect_success 'multiple files per node' "
echo e >/tmp/slsm/e &&
echo f >/tmp/slsm/f &&
\
rules f=/tmp/slsm/c a=$CAT p=0 '' \
f=/tmp/slsm/b a=$CAT p=0 '' \
f=/tmp/slsm/a a=$CAT p=0 '' \
f=/tmp/slsm/f a=$HEAD p=0 '' \
f=/tmp/slsm/e a=$HEAD p=0 '' \
f=/tmp/slsm/d a=$HEAD p=0 '' \
f=/tmp/slsm/e a=$PERL p=2 '' \
f=/tmp/slsm/d a=$PERL p=0 '' \
f=/tmp/slsm/f a=$PERL p=0 &&
rules p=/tmp/slsm/c a=$CAT m=0 '' \
p=/tmp/slsm/b a=$CAT m=0 '' \
p=/tmp/slsm/a a=$CAT m=0 '' \
p=/tmp/slsm/f a=$HEAD m=0 '' \
p=/tmp/slsm/e a=$HEAD m=0 '' \
p=/tmp/slsm/d a=$HEAD m=0 '' \
p=/tmp/slsm/e a=$PERL m=2 '' \
p=/tmp/slsm/d a=$PERL m=0 '' \
p=/tmp/slsm/f a=$PERL m=0 &&
test_must_fail $CAT /tmp/slsm/a &&
test_must_fail $CAT /tmp/slsm/b &&
test_must_fail $CAT /tmp/slsm/c &&
......@@ -330,9 +330,9 @@ test_expect_success 'example SSH private key setup' "
echo pub >/tmp/slsm/home/user/.ssh/id_rsa.pub &&
echo cfg >/tmp/slsm/home/user/.ssh/config &&
\
rules f=/tmp/slsm/home/user/.ssh/private p=0 '' \
f=/tmp/slsm/home/user/.ssh/private a=$HEAD p=4 '' \
f=/tmp/slsm/home/user/.ssh/id_rsa.pub p=4 &&
rules p=/tmp/slsm/home/user/.ssh/private m=0 '' \
p=/tmp/slsm/home/user/.ssh/private a=$HEAD m=4 '' \
p=/tmp/slsm/home/user/.ssh/id_rsa.pub m=4 &&
echo cfg >expected &&
test_cmp expected /tmp/slsm/home/user/.ssh/config &&
rm /tmp/slsm/home/user/.ssh/config &&
......@@ -362,20 +362,20 @@ test_expect_success 'example mpv setup' "
echo movie >/tmp/slsm/home/user/Movies/movie &&
echo cfg >/tmp/slsm/home/user/.config/mpv/mpv.conf &&
\
rules f=/ a=$PERL p=0 '' \
f=/etc a=$PERL p=4 '' \
f=/lib a=$PERL p=4 '' \
f=/proc a=$PERL p=4 '' \
f=/sys a=$PERL p=4 '' \
f=/usr a=$PERL p=4 '' \
f=/dev a=$PERL p=6 '' \
f=/usr/bin/head a=$PERL p=13 '' \
f=/tmp/slsm/home/ a=$PERL p=0 '' \
f=/tmp/slsm/home/user/Downloads a=$PERL p=4 '' \
f=/tmp/slsm/home/user/Music a=$PERL p=4 '' \
f=/tmp/slsm/home/user/Movies a=$PERL p=4 '' \
f=/tmp/slsm/home/user/.config/mpv a=$PERL p=4 '' \
f=/tmp/slsm/home/user/.config/mpv/watch_later a=$PERL p=6 &&
rules p=/ a=$PERL m=0 '' \
p=/etc a=$PERL m=4 '' \
p=/lib a=$PERL m=4 '' \
p=/proc a=$PERL m=4 '' \
p=/sys a=$PERL m=4 '' \
p=/usr a=$PERL m=4 '' \
p=/dev a=$PERL m=6 '' \
p=/usr/bin/head a=$PERL m=5 f=1 '' \
p=/tmp/slsm/home/ a=$PERL m=0 '' \
p=/tmp/slsm/home/user/Downloads a=$PERL m=4 '' \
p=/tmp/slsm/home/user/Music a=$PERL m=4 '' \
p=/tmp/slsm/home/user/Movies a=$PERL m=4 '' \
p=/tmp/slsm/home/user/.config/mpv a=$PERL m=4 '' \
p=/tmp/slsm/home/user/.config/mpv/watch_later a=$PERL m=6 &&
echo file >expected &&
$PERL -e 'print (<> or exit 1)' /tmp/slsm/home/user/Downloads/file >actual &&
test_cmp expected actual &&
......
......@@ -84,9 +84,9 @@ static struct tree_node *slsm_find_matching_child(const struct tree_node *t,
* slsm_last_match - find the last match in a ruleset
* @t: node in which we search
* @app: application we are looking for
* @mode: where to write the new mode if one is found;
* @perms: where to write the new perms if one is found;
*/
static void slsm_last_match(const struct tree_node *t, const char *app, unsigned *mode) {
static void slsm_last_match(const struct tree_node *t, const char *app, struct slsm_perms *perms) {
size_t i;
if (!t->rules || t->rules_used == 0)
......@@ -95,7 +95,7 @@ static void slsm_last_match(const struct tree_node *t, const char *app, unsigned
i = t->rules_used - 1;
do {
if (!t->rules[i].app || !strcmp(t->rules[i].app, app)) {
*mode = t->rules[i].mode;
*perms = t->rules[i].perms;
return;
}
} while (i-- > 0);
......@@ -103,16 +103,16 @@ static void slsm_last_match(const struct tree_node *t, const char *app, unsigned
/**
* slsm_query_mode - query the applying mode
* slsm_query_perms - query the applying perms
* @path: the path in question (object)
* @app: the application (subject)
*
* Returns: the mode for @app at @path or SLSM_UNRESTRICTED
* Returns: the perms for @app at @path or SLSM_UNRESTRICTED
*/
unsigned slsm_query_mode(const char *path, const char *app) {
struct slsm_perms slsm_query_perms(const char *path, const char *app) {
const char *component;
struct tree_node *t;
unsigned ret = SLSM_UNRESTRICTED;
struct slsm_perms ret = { .mode = SLSM_MODE_RWX, .flags = 0 };
if (!rules)
return ret;
......@@ -141,6 +141,9 @@ unsigned slsm_query_mode(const char *path, const char *app) {
return ret;
}
unsigned slsm_perms_mode_grant(struct slsm_perms perms, struct slsm_perms perms_want) {
return (perms.mode & perms_want.mode) == perms_want.mode;
}
......@@ -289,8 +292,8 @@ static const char *slsm_parse_component(const char *rule, size_t *remaining) {
*/
static int slsm_insert_rule(struct tree_node *t, const char *rule,
size_t *remaining) {
const char *app = NULL, *path = NULL, *perm_str = NULL;
struct slsm_rule r;
const char *app = NULL, *path = NULL, *mode_str = NULL, *flags_str = NULL;
struct slsm_rule r = { .app = NULL, .perms = { .mode = 0, .flags = 0 }};
char *path_components = NULL;
int error = 0;
......@@ -304,50 +307,50 @@ static int slsm_insert_rule(struct tree_node *t, const char *rule,
switch (c) {
case 'a':
app = rule + 1;
rule = slsm_parse_component(rule, remaining);
if (!rule) {
printk(KERN_ERR "slsm_insert_rule: format error after key 'a'\n");
return -EINVAL;
}
break;
case 'f':
path = rule + 1;
rule = slsm_parse_component(rule, remaining);
if (!rule) {
printk(KERN_ERR "slsm_insert_rule: format error after key 'f'\n");
return -EINVAL;
}
break;
goto parse_component;
case 'p':
perm_str = rule + 1;
rule = slsm_parse_component(rule, remaining);
if (!rule) {
printk(KERN_ERR "slsm_insert_rule: format error after key 'p'\n");
return -EINVAL;
}
break;
path = rule + 1;
goto parse_component;
case 'm':
mode_str = rule + 1;
goto parse_component;
case 'f':
flags_str = rule + 1;
goto parse_component;
case '\0':
goto insert;
default:
printk(KERN_ERR "slsm_insert_rule: unexpected char %c\n", c);
return -EINVAL;
}
parse_component:
rule = slsm_parse_component(rule, remaining);
if (!rule) {
printk(KERN_ERR "slsm_insert_rule: format error after key '%c'\n", c);
return -EINVAL;
}
}
insert:
printk(KERN_INFO "slsm: adding f=%s, a=%s, p=%s\n", path, app, perm_str);
printk(KERN_INFO "slsm: adding p=%s, a=%s, m=%s\n", path, app, mode_str);
if (!path) {
printk(KERN_ERR "slsm_insert_rule: format error: mandatory parameter path missing\n");
return -EINVAL;
}
if (!perm_str) {
printk(KERN_ERR "slsm_insert_rule: format error: mandatory paremetr permission missing\n");
if (!mode_str) {
printk(KERN_ERR "slsm_insert_rule: format error: mandatory parameter mode missing\n");
return -EINVAL;
}
if ((error = kstrtouint(perm_str, 10, &r.mode))) {
printk(KERN_ERR "slsm_insert_rule: format error: not a number: %s\n",
perm_str);
if ((error = kstrtouint(mode_str, 10, &r.perms.mode))) {
printk(KERN_ERR "slsm_insert_rule: format error: mode not a number: %s\n",
mode_str);
return error;
}
if (flags_str && (error = kstrtouint(flags_str, 10, &r.perms.flags))) {
printk(KERN_ERR "slsm_insert_rule: format error: flags not a number: %s\n",
flags_str);
return error;
}
......
......@@ -27,22 +27,34 @@ struct tree_node {
};
/* "normal" permissions: rwx (usual values) */
#define SLSM_ALLOW_EXEC (1 << 0)
#define SLSM_ALLOW_WRITE (1 << 1)
#define SLSM_ALLOW_READ (1 << 2)
/* label of the execing process is kept */
#define SLSM_INHERIT (1 << 3)
#define SLSM_MODE_X (1 << 0)
#define SLSM_MODE_W (1 << 1)
#define SLSM_MODE_R (1 << 2)
/* all "normal" permissions */
#define SLSM_UNRESTRICTED (SLSM_ALLOW_READ | SLSM_ALLOW_WRITE | SLSM_ALLOW_EXEC)
#define SLSM_MODE_RWX (SLSM_MODE_R | SLSM_MODE_W | SLSM_MODE_X)
#define SLSM_FLAG_INHERIT (1 << 0)
struct slsm_perms {
unsigned mode;
unsigned flags;
};