Smack: Rationalize mount restrictions

The mount restrictions imposed by Smack rely heavily on the
use of the filesystem "floor", which is the label that all
processes writing to the filesystem must have access to. It
turns out that while the "floor" notion is sound, it has yet
to be fully implemented and has never been used.

The sb_mount and sb_umount hooks only make sense if the
filesystem floor is used actively, and it isn't. They can
be reintroduced if a rational restriction comes up. Until
then, they get removed.

The sb_kern_mount hook is required for the option processing.
It is too permissive in the case of unprivileged mounts,
effectively bypassing the CAP_MAC_ADMIN restrictions if
any of the smack options are specified. Unprivileged mounts
are no longer allowed to set Smack filesystem options.
Additionally, the root and default values are set to the
label of the caller, in keeping with the policy that objects
get the label of their creator.

Targeted for git://git.gitorious.org/smack-next/kernel.git

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
This commit is contained in:
Casey Schaufler 2013-12-30 09:38:00 -08:00
parent 4afde48be8
commit 24ea1b6efc

View File

@ -229,7 +229,7 @@ static int smack_syslog(int typefrom_file)
if (smack_privileged(CAP_MAC_OVERRIDE))
return 0;
if (smack_syslog_label != NULL && smack_syslog_label != skp)
if (smack_syslog_label != NULL && smack_syslog_label != skp)
rc = -EACCES;
return rc;
@ -339,10 +339,12 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
struct inode *inode = root->d_inode;
struct superblock_smack *sp = sb->s_security;
struct inode_smack *isp;
struct smack_known *skp;
char *op;
char *commap;
char *nsp;
int transmute = 0;
int specified = 0;
if (sp->smk_initialized)
return 0;
@ -357,34 +359,56 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) {
op += strlen(SMK_FSHAT);
nsp = smk_import(op, 0);
if (nsp != NULL)
if (nsp != NULL) {
sp->smk_hat = nsp;
specified = 1;
}
} else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) {
op += strlen(SMK_FSFLOOR);
nsp = smk_import(op, 0);
if (nsp != NULL)
if (nsp != NULL) {
sp->smk_floor = nsp;
specified = 1;
}
} else if (strncmp(op, SMK_FSDEFAULT,
strlen(SMK_FSDEFAULT)) == 0) {
op += strlen(SMK_FSDEFAULT);
nsp = smk_import(op, 0);
if (nsp != NULL)
if (nsp != NULL) {
sp->smk_default = nsp;
specified = 1;
}
} else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) {
op += strlen(SMK_FSROOT);
nsp = smk_import(op, 0);
if (nsp != NULL)
if (nsp != NULL) {
sp->smk_root = nsp;
specified = 1;
}
} else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) {
op += strlen(SMK_FSTRANS);
nsp = smk_import(op, 0);
if (nsp != NULL) {
sp->smk_root = nsp;
transmute = 1;
specified = 1;
}
}
}
if (!smack_privileged(CAP_MAC_ADMIN)) {
/*
* Unprivileged mounts don't get to specify Smack values.
*/
if (specified)
return -EPERM;
/*
* Unprivileged mounts get root and default from the caller.
*/
skp = smk_of_current();
sp->smk_root = skp->smk_known;
sp->smk_default = skp->smk_known;
}
/*
* Initialize the root inode.
*/
@ -421,53 +445,6 @@ static int smack_sb_statfs(struct dentry *dentry)
return rc;
}
/**
* smack_sb_mount - Smack check for mounting
* @dev_name: unused
* @path: mount point
* @type: unused
* @flags: unused
* @data: unused
*
* Returns 0 if current can write the floor of the filesystem
* being mounted on, an error code otherwise.
*/
static int smack_sb_mount(const char *dev_name, struct path *path,
const char *type, unsigned long flags, void *data)
{
struct superblock_smack *sbp = path->dentry->d_sb->s_security;
struct smk_audit_info ad;
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
smk_ad_setfield_u_fs_path(&ad, *path);
return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad);
}
/**
* smack_sb_umount - Smack check for unmounting
* @mnt: file system to unmount
* @flags: unused
*
* Returns 0 if current can write the floor of the filesystem
* being unmounted, an error code otherwise.
*/
static int smack_sb_umount(struct vfsmount *mnt, int flags)
{
struct superblock_smack *sbp;
struct smk_audit_info ad;
struct path path;
path.dentry = mnt->mnt_root;
path.mnt = mnt;
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
smk_ad_setfield_u_fs_path(&ad, path);
sbp = path.dentry->d_sb->s_security;
return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad);
}
/*
* BPRM hooks
*/
@ -3762,8 +3739,6 @@ struct security_operations smack_ops = {
.sb_copy_data = smack_sb_copy_data,
.sb_kern_mount = smack_sb_kern_mount,
.sb_statfs = smack_sb_statfs,
.sb_mount = smack_sb_mount,
.sb_umount = smack_sb_umount,
.bprm_set_creds = smack_bprm_set_creds,
.bprm_committing_creds = smack_bprm_committing_creds,