Skip to content

Commit

Permalink
Merge tag 'selinux-pr-20200330' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/kernel/git/pcmoore/selinux

Pull SELinux updates from Paul Moore:
 "We've got twenty SELinux patches for the v5.7 merge window, the
  highlights are below:

   - Deprecate setting /sys/fs/selinux/checkreqprot to 1.

     This flag was originally created to deal with legacy userspace and
     the READ_IMPLIES_EXEC personality flag. We changed the default from
     1 to 0 back in Linux v4.4 and now we are taking the next step of
     deprecating it, at some point in the future we will take the final
     step of rejecting 1.

   - Allow kernfs symlinks to inherit the SELinux label of the parent
     directory. In order to preserve backwards compatibility this is
     protected by the genfs_seclabel_symlinks SELinux policy capability.

   - Optimize how we store filename transitions in the kernel, resulting
     in some significant improvements to policy load times.

   - Do a better job calculating our internal hash table sizes which
     resulted in additional policy load improvements and likely general
     SELinux performance improvements as well.

   - Remove the unused initial SIDs (labels) and improve how we handle
     initial SIDs.

   - Enable per-file labeling for the bpf filesystem.

   - Ensure that we properly label NFS v4.2 filesystems to avoid a
     temporary unlabeled condition.

   - Add some missing XFS quota command types to the SELinux quota
     access controls.

   - Fix a problem where we were not updating the seq_file position
     index correctly in selinuxfs.

   - We consolidate some duplicated code into helper functions.

   - A number of list to array conversions.

   - Update Stephen Smalley's email address in MAINTAINERS"

* tag 'selinux-pr-20200330' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux:
  selinux: clean up indentation issue with assignment statement
  NFS: Ensure security label is set for root inode
  MAINTAINERS: Update my email address
  selinux: avtab_init() and cond_policydb_init() return void
  selinux: clean up error path in policydb_init()
  selinux: remove unused initial SIDs and improve handling
  selinux: reduce the use of hard-coded hash sizes
  selinux: Add xfs quota command types
  selinux: optimize storage of filename transitions
  selinux: factor out loop body from filename_trans_read()
  security: selinux: allow per-file labeling for bpffs
  selinux: generalize evaluate_cond_node()
  selinux: convert cond_expr to array
  selinux: convert cond_av_list to array
  selinux: convert cond_list to array
  selinux: sel_avc_get_stat_idx should increase position index
  selinux: allow kernfs symlinks to inherit parent directory context
  selinux: simplify evaluate_cond_node()
  Documentation,selinux: deprecate setting checkreqprot to 1
  selinux: move status variables out of selinux_ss
  • Loading branch information
torvalds committed Mar 31, 2020
2 parents 674d85e + c753924 commit b3aa112
Show file tree
Hide file tree
Showing 26 changed files with 521 additions and 490 deletions.
23 changes: 23 additions & 0 deletions Documentation/ABI/obsolete/sysfs-selinux-checkreqprot
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
What: /sys/fs/selinux/checkreqprot
Date: April 2005 (predates git)
KernelVersion: 2.6.12-rc2 (predates git)
Contact: [email protected]
Description:

The selinuxfs "checkreqprot" node allows SELinux to be configured
to check the protection requested by userspace for mmap/mprotect
calls instead of the actual protection applied by the kernel.
This was a compatibility mechanism for legacy userspace and
for the READ_IMPLIES_EXEC personality flag. However, if set to
1, it weakens security by allowing mappings to be made executable
without authorization by policy. The default value of checkreqprot
at boot was changed starting in Linux v4.4 to 0 (i.e. check the
actual protection), and Android and Linux distributions have been
explicitly writing a "0" to /sys/fs/selinux/checkreqprot during
initialization for some time. Support for setting checkreqprot to 1
will be removed in a future kernel release, at which point the kernel
will always cease using checkreqprot internally and will always
check the actual protections being applied upon mmap/mprotect calls.
The checkreqprot selinuxfs node will remain for backward compatibility
but will discard writes of the "0" value and will reject writes of the
"1" value when this mechanism is removed.
1 change: 1 addition & 0 deletions Documentation/admin-guide/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,7 @@
Default value is set via a kernel config option.
Value can be changed at runtime via
/sys/fs/selinux/checkreqprot.
Setting checkreqprot to 1 is deprecated.

cio_ignore= [S390]
See Documentation/s390/common_io.rst for details.
Expand Down
3 changes: 2 additions & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -15027,7 +15027,7 @@ X: security/selinux/

SELINUX SECURITY MODULE
M: Paul Moore <[email protected]>
M: Stephen Smalley <[email protected]>
M: Stephen Smalley <[email protected]>
M: Eric Paris <[email protected]>
L: [email protected]
W: https://selinuxproject.org
Expand All @@ -15039,6 +15039,7 @@ F: security/selinux/
F: scripts/selinux/
F: Documentation/admin-guide/LSM/SELinux.rst
F: Documentation/ABI/obsolete/sysfs-selinux-disable
F: Documentation/ABI/obsolete/sysfs-selinux-checkreqprot

SENSABLE PHANTOM
M: Jiri Slaby <[email protected]>
Expand Down
39 changes: 35 additions & 4 deletions fs/nfs/getroot.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ int nfs_get_root(struct super_block *s, struct fs_context *fc)
struct inode *inode;
char *name;
int error = -ENOMEM;
unsigned long kflags = 0, kflags_out = 0;

name = kstrdup(fc->source, GFP_KERNEL);
if (!name)
Expand All @@ -83,24 +84,27 @@ int nfs_get_root(struct super_block *s, struct fs_context *fc)
if (fsinfo.fattr == NULL)
goto out_name;

fsinfo.fattr->label = nfs4_label_alloc(server, GFP_KERNEL);
if (IS_ERR(fsinfo.fattr->label))
goto out_fattr;
error = server->nfs_client->rpc_ops->getroot(server, ctx->mntfh, &fsinfo);
if (error < 0) {
dprintk("nfs_get_root: getattr error = %d\n", -error);
nfs_errorf(fc, "NFS: Couldn't getattr on root");
goto out_fattr;
goto out_label;
}

inode = nfs_fhget(s, ctx->mntfh, fsinfo.fattr, NULL);
if (IS_ERR(inode)) {
dprintk("nfs_get_root: get root inode failed\n");
error = PTR_ERR(inode);
nfs_errorf(fc, "NFS: Couldn't get root inode");
goto out_fattr;
goto out_label;
}

error = nfs_superblock_set_dummy_root(s, inode);
if (error != 0)
goto out_fattr;
goto out_label;

/* root dentries normally start off anonymous and get spliced in later
* if the dentry tree reaches them; however if the dentry already
Expand All @@ -111,7 +115,7 @@ int nfs_get_root(struct super_block *s, struct fs_context *fc)
dprintk("nfs_get_root: get root dentry failed\n");
error = PTR_ERR(root);
nfs_errorf(fc, "NFS: Couldn't get root dentry");
goto out_fattr;
goto out_label;
}

security_d_instantiate(root, inode);
Expand All @@ -123,12 +127,39 @@ int nfs_get_root(struct super_block *s, struct fs_context *fc)
}
spin_unlock(&root->d_lock);
fc->root = root;
if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL)
kflags |= SECURITY_LSM_NATIVE_LABELS;
if (ctx->clone_data.sb) {
if (d_inode(fc->root)->i_fop != &nfs_dir_operations) {
error = -ESTALE;
goto error_splat_root;
}
/* clone lsm security options from the parent to the new sb */
error = security_sb_clone_mnt_opts(ctx->clone_data.sb,
s, kflags, &kflags_out);
} else {
error = security_sb_set_mnt_opts(s, fc->security,
kflags, &kflags_out);
}
if (error)
goto error_splat_root;
if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL &&
!(kflags_out & SECURITY_LSM_NATIVE_LABELS))
NFS_SB(s)->caps &= ~NFS_CAP_SECURITY_LABEL;

nfs_setsecurity(inode, fsinfo.fattr, fsinfo.fattr->label);
error = 0;

out_label:
nfs4_label_free(fsinfo.fattr->label);
out_fattr:
nfs_free_fattr(fsinfo.fattr);
out_name:
kfree(name);
out:
return error;
error_splat_root:
dput(fc->root);
fc->root = NULL;
goto out_label;
}
12 changes: 3 additions & 9 deletions fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -4002,31 +4002,25 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *mntfh,
{
int error;
struct nfs_fattr *fattr = info->fattr;
struct nfs4_label *label = NULL;
struct nfs4_label *label = fattr->label;

error = nfs4_server_capabilities(server, mntfh);
if (error < 0) {
dprintk("nfs4_get_root: getcaps error = %d\n", -error);
return error;
}

label = nfs4_label_alloc(server, GFP_KERNEL);
if (IS_ERR(label))
return PTR_ERR(label);

error = nfs4_proc_getattr(server, mntfh, fattr, label, NULL);
if (error < 0) {
dprintk("nfs4_get_root: getattr error = %d\n", -error);
goto err_free_label;
goto out;
}

if (fattr->valid & NFS_ATTR_FATTR_FSID &&
!nfs_fsid_equal(&server->fsid, &fattr->fsid))
memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid));

err_free_label:
nfs4_label_free(label);

out:
return error;
}

Expand Down
25 changes: 0 additions & 25 deletions fs/nfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1179,7 +1179,6 @@ int nfs_get_tree_common(struct fs_context *fc)
struct super_block *s;
int (*compare_super)(struct super_block *, struct fs_context *) = nfs_compare_super;
struct nfs_server *server = ctx->server;
unsigned long kflags = 0, kflags_out = 0;
int error;

ctx->server = NULL;
Expand Down Expand Up @@ -1239,26 +1238,6 @@ int nfs_get_tree_common(struct fs_context *fc)
goto error_splat_super;
}

if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL)
kflags |= SECURITY_LSM_NATIVE_LABELS;
if (ctx->clone_data.sb) {
if (d_inode(fc->root)->i_fop != &nfs_dir_operations) {
error = -ESTALE;
goto error_splat_root;
}
/* clone any lsm security options from the parent to the new sb */
error = security_sb_clone_mnt_opts(ctx->clone_data.sb, s, kflags,
&kflags_out);
} else {
error = security_sb_set_mnt_opts(s, fc->security,
kflags, &kflags_out);
}
if (error)
goto error_splat_root;
if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL &&
!(kflags_out & SECURITY_LSM_NATIVE_LABELS))
NFS_SB(s)->caps &= ~NFS_CAP_SECURITY_LABEL;

s->s_flags |= SB_ACTIVE;
error = 0;

Expand All @@ -1268,10 +1247,6 @@ int nfs_get_tree_common(struct fs_context *fc)
out_err_nosb:
nfs_free_server(server);
goto out;

error_splat_root:
dput(fc->root);
fc->root = NULL;
error_splat_super:
deactivate_locked_super(s);
goto out;
Expand Down
1 change: 1 addition & 0 deletions include/linux/nfs_xdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ struct nfs_fattr {
struct nfs4_string *owner_name;
struct nfs4_string *group_name;
struct nfs4_threshold *mdsthreshold; /* pNFS threshold hints */
struct nfs4_label *label;
};

#define NFS_ATTR_FATTR_TYPE (1U << 0)
Expand Down
11 changes: 8 additions & 3 deletions scripts/selinux/genheaders/genheaders.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,12 @@ int main(int argc, char *argv[])
}

isids_len = sizeof(initial_sid_to_string) / sizeof (char *);
for (i = 1; i < isids_len; i++)
initial_sid_to_string[i] = stoupperx(initial_sid_to_string[i]);
for (i = 1; i < isids_len; i++) {
const char *s = initial_sid_to_string[i];

if (s)
initial_sid_to_string[i] = stoupperx(s);
}

fprintf(fout, "/* This file is automatically generated. Do not edit. */\n");
fprintf(fout, "#ifndef _SELINUX_FLASK_H_\n#define _SELINUX_FLASK_H_\n\n");
Expand All @@ -82,7 +86,8 @@ int main(int argc, char *argv[])

for (i = 1; i < isids_len; i++) {
const char *s = initial_sid_to_string[i];
fprintf(fout, "#define SECINITSID_%-39s %2d\n", s, i);
if (s)
fprintf(fout, "#define SECINITSID_%-39s %2d\n", s, i);
}
fprintf(fout, "\n#define SECINITSID_NUM %d\n", i-1);
fprintf(fout, "\nstatic inline bool security_is_socket_class(u16 kern_tclass)\n");
Expand Down
3 changes: 3 additions & 0 deletions security/selinux/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ config SECURITY_SELINUX_CHECKREQPROT_VALUE
'checkreqprot=' boot parameter. It may also be changed at runtime
via /sys/fs/selinux/checkreqprot if authorized by policy.

WARNING: this option is deprecated and will be removed in a future
kernel release.

If you are unsure how to answer this question, answer 0.

config SECURITY_SELINUX_SIDTAB_HASH_BITS
Expand Down
4 changes: 2 additions & 2 deletions security/selinux/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
obj-$(CONFIG_SECURITY_SELINUX) := selinux.o

selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o \
netnode.o netport.o \
netnode.o netport.o status.o \
ss/ebitmap.o ss/hashtab.o ss/symtab.o ss/sidtab.o ss/avtab.o \
ss/policydb.o ss/services.o ss/conditional.o ss/mls.o ss/status.o
ss/policydb.o ss/services.o ss/conditional.o ss/mls.o

selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o

Expand Down
18 changes: 16 additions & 2 deletions security/selinux/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,11 @@ static int __init checkreqprot_setup(char *str)
{
unsigned long checkreqprot;

if (!kstrtoul(str, 0, &checkreqprot))
if (!kstrtoul(str, 0, &checkreqprot)) {
selinux_checkreqprot_boot = checkreqprot ? 1 : 0;
if (checkreqprot)
pr_warn("SELinux: checkreqprot set to 1 via kernel parameter. This is deprecated and will be rejected in a future kernel release.\n");
}
return 1;
}
__setup("checkreqprot=", checkreqprot_setup);
Expand Down Expand Up @@ -699,6 +702,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
if (!strcmp(sb->s_type->name, "debugfs") ||
!strcmp(sb->s_type->name, "tracefs") ||
!strcmp(sb->s_type->name, "binder") ||
!strcmp(sb->s_type->name, "bpf") ||
!strcmp(sb->s_type->name, "pstore"))
sbsec->flags |= SE_SBGENFS;

Expand Down Expand Up @@ -1475,7 +1479,9 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
/* Default to the fs superblock SID. */
sid = sbsec->sid;

if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
if ((sbsec->flags & SE_SBGENFS) &&
(!S_ISLNK(inode->i_mode) ||
selinux_policycap_genfs_seclabel_symlinks())) {
/* We must have a dentry to determine the label on
* procfs inodes */
if (opt_dentry) {
Expand Down Expand Up @@ -2139,11 +2145,18 @@ static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
case Q_QUOTAOFF:
case Q_SETINFO:
case Q_SETQUOTA:
case Q_XQUOTAOFF:
case Q_XQUOTAON:
case Q_XSETQLIM:
rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
break;
case Q_GETFMT:
case Q_GETINFO:
case Q_GETQUOTA:
case Q_XGETQUOTA:
case Q_XGETQSTAT:
case Q_XGETQSTATV:
case Q_XGETNEXTQUOTA:
rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
break;
default:
Expand Down Expand Up @@ -7161,6 +7174,7 @@ static __init int selinux_init(void)
selinux_state.checkreqprot = selinux_checkreqprot_boot;
selinux_ss_init(&selinux_state.ss);
selinux_avc_init(&selinux_state.avc);
mutex_init(&selinux_state.status_lock);

/* Set the security state for the initial task. */
cred_init_security();
Expand Down
8 changes: 3 additions & 5 deletions security/selinux/include/conditional.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@
#include "security.h"

int security_get_bools(struct selinux_state *state,
int *len, char ***names, int **values);
u32 *len, char ***names, int **values);

int security_set_bools(struct selinux_state *state,
int len, int *values);
int security_set_bools(struct selinux_state *state, u32 len, int *values);

int security_get_bool_value(struct selinux_state *state,
int index);
int security_get_bool_value(struct selinux_state *state, u32 index);

#endif
Loading

0 comments on commit b3aa112

Please sign in to comment.