Skip to content

Commit

Permalink
Merge tag 'selinux-pr-20210426' 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:

 - Add support for measuring the SELinux state and policy capabilities
   using IMA.

 - A handful of SELinux/NFS patches to compare the SELinux state of one
   mount with a set of mount options. Olga goes into more detail in the
   patch descriptions, but this is important as it allows more
   flexibility when using NFS and SELinux context mounts.

 - Properly differentiate between the subjective and objective LSM
   credentials; including support for the SELinux and Smack. My clumsy
   attempt at a proper fix for AppArmor didn't quite pass muster so John
   is working on a proper AppArmor patch, in the meantime this set of
   patches shouldn't change the behavior of AppArmor in any way. This
   change explains the bulk of the diffstat beyond security/.

 - Fix a problem where we were not properly terminating the permission
   list for two SELinux object classes.

* tag 'selinux-pr-20210426' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux:
  selinux: add proper NULL termination to the secclass_map permissions
  smack: differentiate between subjective and objective task credentials
  selinux: clarify task subjective and objective credentials
  lsm: separate security_task_getsecid() into subjective and objective variants
  nfs: account for selinux security context when deciding to share superblock
  nfs: remove unneeded null check in nfs_fill_super()
  lsm,selinux: add new hook to compare new mount to an existing mount
  selinux: fix misspellings using codespell tool
  selinux: fix misspellings using codespell tool
  selinux: measure state and policy capabilities
  selinux: Allow context mounts for unpriviliged overlayfs
  • Loading branch information
torvalds committed Apr 27, 2021
2 parents fafe1e3 + e4c82ea commit f1c921f
Show file tree
Hide file tree
Showing 29 changed files with 372 additions and 92 deletions.
11 changes: 10 additions & 1 deletion drivers/android/binder.c
Original file line number Diff line number Diff line change
Expand Up @@ -2713,7 +2713,16 @@ static void binder_transaction(struct binder_proc *proc,
u32 secid;
size_t added_size;

security_task_getsecid(proc->tsk, &secid);
/*
* Arguably this should be the task's subjective LSM secid but
* we can't reliably access the subjective creds of a task
* other than our own so we must use the objective creds, which
* are safe to access. The downside is that if a task is
* temporarily overriding it's creds it will not be reflected
* here; however, it isn't clear that binder would handle that
* case well anyway.
*/
security_task_getsecid_obj(proc->tsk, &secid);
ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
if (ret) {
return_error = BR_FAILED_REPLY;
Expand Down
3 changes: 3 additions & 0 deletions fs/nfs/fs_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,9 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
if (opt < 0)
return ctx->sloppy ? 1 : opt;

if (fc->security)
ctx->has_sec_mnt_opts = 1;

switch (opt) {
case Opt_source:
if (fc->source)
Expand Down
1 change: 1 addition & 0 deletions fs/nfs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ struct nfs_fs_context {
char *fscache_uniq;
unsigned short protofamily;
unsigned short mountfamily;
bool has_sec_mnt_opts;

struct {
union {
Expand Down
6 changes: 5 additions & 1 deletion fs/nfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1045,7 +1045,7 @@ static void nfs_fill_super(struct super_block *sb, struct nfs_fs_context *ctx)
sb->s_blocksize = 0;
sb->s_xattr = server->nfs_client->cl_nfs_mod->xattr;
sb->s_op = server->nfs_client->cl_nfs_mod->sops;
if (ctx && ctx->bsize)
if (ctx->bsize)
sb->s_blocksize = nfs_block_size(ctx->bsize, &sb->s_blocksize_bits);

if (server->nfs_client->rpc_ops->version != 2) {
Expand Down Expand Up @@ -1077,6 +1077,7 @@ static void nfs_fill_super(struct super_block *sb, struct nfs_fs_context *ctx)
&sb->s_blocksize_bits);

nfs_super_set_maxbytes(sb, server->maxfilesize);
server->has_sec_mnt_opts = ctx->has_sec_mnt_opts;
}

static int nfs_compare_mount_options(const struct super_block *s, const struct nfs_server *b,
Expand Down Expand Up @@ -1193,6 +1194,9 @@ static int nfs_compare_super(struct super_block *sb, struct fs_context *fc)
return 0;
if (!nfs_compare_userns(old, server))
return 0;
if ((old->has_sec_mnt_opts || fc->security) &&
security_sb_mnt_opts_compat(sb, fc->security))
return 0;
return nfs_compare_mount_options(sb, server, fc);
}

Expand Down
2 changes: 1 addition & 1 deletion include/linux/cred.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ struct cred {
struct key *request_key_auth; /* assumed request_key authority */
#endif
#ifdef CONFIG_SECURITY
void *security; /* subjective LSM security */
void *security; /* LSM security */
#endif
struct user_struct *user; /* real user ID subscription */
struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */
Expand Down
6 changes: 5 additions & 1 deletion include/linux/lsm_hook_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ LSM_HOOK(int, 0, sb_alloc_security, struct super_block *sb)
LSM_HOOK(void, LSM_RET_VOID, sb_free_security, struct super_block *sb)
LSM_HOOK(void, LSM_RET_VOID, sb_free_mnt_opts, void *mnt_opts)
LSM_HOOK(int, 0, sb_eat_lsm_opts, char *orig, void **mnt_opts)
LSM_HOOK(int, 0, sb_mnt_opts_compat, struct super_block *sb, void *mnt_opts)
LSM_HOOK(int, 0, sb_remount, struct super_block *sb, void *mnt_opts)
LSM_HOOK(int, 0, sb_kern_mount, struct super_block *sb)
LSM_HOOK(int, 0, sb_show_options, struct seq_file *m, struct super_block *sb)
Expand Down Expand Up @@ -203,7 +204,10 @@ LSM_HOOK(int, 0, task_fix_setgid, struct cred *new, const struct cred * old,
LSM_HOOK(int, 0, task_setpgid, struct task_struct *p, pid_t pgid)
LSM_HOOK(int, 0, task_getpgid, struct task_struct *p)
LSM_HOOK(int, 0, task_getsid, struct task_struct *p)
LSM_HOOK(void, LSM_RET_VOID, task_getsecid, struct task_struct *p, u32 *secid)
LSM_HOOK(void, LSM_RET_VOID, task_getsecid_subj,
struct task_struct *p, u32 *secid)
LSM_HOOK(void, LSM_RET_VOID, task_getsecid_obj,
struct task_struct *p, u32 *secid)
LSM_HOOK(int, 0, task_setnice, struct task_struct *p, int nice)
LSM_HOOK(int, 0, task_setioprio, struct task_struct *p, int ioprio)
LSM_HOOK(int, 0, task_getioprio, struct task_struct *p)
Expand Down
18 changes: 15 additions & 3 deletions include/linux/lsm_hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@
* @orig the original mount data copied from userspace.
* @copy copied data which will be passed to the security module.
* Returns 0 if the copy was successful.
* @sb_mnt_opts_compat:
* Determine if the new mount options in @mnt_opts are allowed given
* the existing mounted filesystem at @sb.
* @sb superblock being compared
* @mnt_opts new mount options
* Return 0 if options are compatible.
* @sb_remount:
* Extracts security system specific mount options and verifies no changes
* are being made to those options.
Expand Down Expand Up @@ -707,9 +713,15 @@
* @p.
* @p contains the task_struct for the process.
* Return 0 if permission is granted.
* @task_getsecid:
* Retrieve the security identifier of the process @p.
* @p contains the task_struct for the process and place is into @secid.
* @task_getsecid_subj:
* Retrieve the subjective security identifier of the task_struct in @p
* and return it in @secid. Special care must be taken to ensure that @p
* is the either the "current" task, or the caller has exclusive access
* to @p.
* In case of failure, @secid will be set to zero.
* @task_getsecid_obj:
* Retrieve the objective security identifier of the task_struct in @p
* and return it in @secid.
* In case of failure, @secid will be set to zero.
*
* @task_setnice:
Expand Down
1 change: 1 addition & 0 deletions include/linux/nfs_fs_sb.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ struct nfs_server {

/* User namespace info */
const struct cred *cred;
bool has_sec_mnt_opts;
};

/* Server capabilities */
Expand Down
18 changes: 16 additions & 2 deletions include/linux/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ int security_sb_alloc(struct super_block *sb);
void security_sb_free(struct super_block *sb);
void security_free_mnt_opts(void **mnt_opts);
int security_sb_eat_lsm_opts(char *options, void **mnt_opts);
int security_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts);
int security_sb_remount(struct super_block *sb, void *mnt_opts);
int security_sb_kern_mount(struct super_block *sb);
int security_sb_show_options(struct seq_file *m, struct super_block *sb);
Expand Down Expand Up @@ -414,7 +415,8 @@ int security_task_fix_setgid(struct cred *new, const struct cred *old,
int security_task_setpgid(struct task_struct *p, pid_t pgid);
int security_task_getpgid(struct task_struct *p);
int security_task_getsid(struct task_struct *p);
void security_task_getsecid(struct task_struct *p, u32 *secid);
void security_task_getsecid_subj(struct task_struct *p, u32 *secid);
void security_task_getsecid_obj(struct task_struct *p, u32 *secid);
int security_task_setnice(struct task_struct *p, int nice);
int security_task_setioprio(struct task_struct *p, int ioprio);
int security_task_getioprio(struct task_struct *p);
Expand Down Expand Up @@ -646,6 +648,13 @@ static inline int security_sb_remount(struct super_block *sb,
return 0;
}

static inline int security_sb_mnt_opts_compat(struct super_block *sb,
void *mnt_opts)
{
return 0;
}


static inline int security_sb_kern_mount(struct super_block *sb)
{
return 0;
Expand Down Expand Up @@ -1098,7 +1107,12 @@ static inline int security_task_getsid(struct task_struct *p)
return 0;
}

static inline void security_task_getsecid(struct task_struct *p, u32 *secid)
static inline void security_task_getsecid_subj(struct task_struct *p, u32 *secid)
{
*secid = 0;
}

static inline void security_task_getsecid_obj(struct task_struct *p, u32 *secid)
{
*secid = 0;
}
Expand Down
4 changes: 2 additions & 2 deletions kernel/audit.c
Original file line number Diff line number Diff line change
Expand Up @@ -2132,7 +2132,7 @@ int audit_log_task_context(struct audit_buffer *ab)
int error;
u32 sid;

security_task_getsecid(current, &sid);
security_task_getsecid_subj(current, &sid);
if (!sid)
return 0;

Expand Down Expand Up @@ -2353,7 +2353,7 @@ int audit_signal_info(int sig, struct task_struct *t)
audit_sig_uid = auid;
else
audit_sig_uid = uid;
security_task_getsecid(current, &audit_sig_sid);
security_task_getsecid_subj(current, &audit_sig_sid);
}

return audit_signal_info_syscall(t);
Expand Down
3 changes: 2 additions & 1 deletion kernel/auditfilter.c
Original file line number Diff line number Diff line change
Expand Up @@ -1359,7 +1359,8 @@ int audit_filter(int msgtype, unsigned int listtype)
case AUDIT_SUBJ_SEN:
case AUDIT_SUBJ_CLR:
if (f->lsm_rule) {
security_task_getsecid(current, &sid);
security_task_getsecid_subj(current,
&sid);
result = security_audit_rule_match(sid,
f->type, f->op, f->lsm_rule);
}
Expand Down
8 changes: 4 additions & 4 deletions kernel/auditsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ static int audit_filter_rules(struct task_struct *tsk,
logged upon error */
if (f->lsm_rule) {
if (need_sid) {
security_task_getsecid(tsk, &sid);
security_task_getsecid_subj(tsk, &sid);
need_sid = 0;
}
result = security_audit_rule_match(sid, f->type,
Expand Down Expand Up @@ -2400,7 +2400,7 @@ void __audit_ptrace(struct task_struct *t)
context->target_auid = audit_get_loginuid(t);
context->target_uid = task_uid(t);
context->target_sessionid = audit_get_sessionid(t);
security_task_getsecid(t, &context->target_sid);
security_task_getsecid_obj(t, &context->target_sid);
memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
}

Expand All @@ -2427,7 +2427,7 @@ int audit_signal_info_syscall(struct task_struct *t)
ctx->target_auid = audit_get_loginuid(t);
ctx->target_uid = t_uid;
ctx->target_sessionid = audit_get_sessionid(t);
security_task_getsecid(t, &ctx->target_sid);
security_task_getsecid_obj(t, &ctx->target_sid);
memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
return 0;
}
Expand All @@ -2448,7 +2448,7 @@ int audit_signal_info_syscall(struct task_struct *t)
axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
axp->target_uid[axp->pid_count] = t_uid;
axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
security_task_getsecid(t, &axp->target_sid[axp->pid_count]);
security_task_getsecid_obj(t, &axp->target_sid[axp->pid_count]);
memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
axp->pid_count++;

Expand Down
3 changes: 2 additions & 1 deletion kernel/bpf/bpf_lsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,8 @@ BTF_ID(func, bpf_lsm_socket_socketpair)

BTF_ID(func, bpf_lsm_syslog)
BTF_ID(func, bpf_lsm_task_alloc)
BTF_ID(func, bpf_lsm_task_getsecid)
BTF_ID(func, bpf_lsm_task_getsecid_subj)
BTF_ID(func, bpf_lsm_task_getsecid_obj)
BTF_ID(func, bpf_lsm_task_prctl)
BTF_ID(func, bpf_lsm_task_setscheduler)
BTF_ID(func, bpf_lsm_task_to_inode)
Expand Down
2 changes: 1 addition & 1 deletion net/netlabel/netlabel_unlabeled.c
Original file line number Diff line number Diff line change
Expand Up @@ -1539,7 +1539,7 @@ int __init netlbl_unlabel_defconf(void)
/* Only the kernel is allowed to call this function and the only time
* it is called is at bootup before the audit subsystem is reporting
* messages so don't worry to much about these values. */
security_task_getsecid(current, &audit_info.secid);
security_task_getsecid_subj(current, &audit_info.secid);
audit_info.loginuid = GLOBAL_ROOT_UID;
audit_info.sessionid = 0;

Expand Down
2 changes: 1 addition & 1 deletion net/netlabel/netlabel_user.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
static inline void netlbl_netlink_auditinfo(struct sk_buff *skb,
struct netlbl_audit *audit_info)
{
security_task_getsecid(current, &audit_info->secid);
security_task_getsecid_subj(current, &audit_info->secid);
audit_info->loginuid = audit_get_loginuid(current);
audit_info->sessionid = audit_get_sessionid(current);
}
Expand Down
3 changes: 2 additions & 1 deletion security/apparmor/lsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1252,7 +1252,8 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {

LSM_HOOK_INIT(task_free, apparmor_task_free),
LSM_HOOK_INIT(task_alloc, apparmor_task_alloc),
LSM_HOOK_INIT(task_getsecid, apparmor_task_getsecid),
LSM_HOOK_INIT(task_getsecid_subj, apparmor_task_getsecid),
LSM_HOOK_INIT(task_getsecid_obj, apparmor_task_getsecid),
LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit),
LSM_HOOK_INIT(task_kill, apparmor_task_kill),

Expand Down
2 changes: 1 addition & 1 deletion security/integrity/ima/ima_appraise.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
if (!ima_appraise)
return 0;

security_task_getsecid(current, &secid);
security_task_getsecid_subj(current, &secid);
return ima_match_policy(mnt_userns, inode, current_cred(), secid, func,
mask, IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL);
}
Expand Down
14 changes: 7 additions & 7 deletions security/integrity/ima/ima_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ int ima_file_mmap(struct file *file, unsigned long prot)
u32 secid;

if (file && (prot & PROT_EXEC)) {
security_task_getsecid(current, &secid);
security_task_getsecid_subj(current, &secid);
return process_measurement(file, current_cred(), secid, NULL,
0, MAY_EXEC, MMAP_CHECK);
}
Expand Down Expand Up @@ -429,7 +429,7 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
!(prot & PROT_EXEC) || (vma->vm_flags & VM_EXEC))
return 0;

security_task_getsecid(current, &secid);
security_task_getsecid_subj(current, &secid);
inode = file_inode(vma->vm_file);
action = ima_get_action(file_mnt_user_ns(vma->vm_file), inode,
current_cred(), secid, MAY_EXEC, MMAP_CHECK,
Expand Down Expand Up @@ -470,7 +470,7 @@ int ima_bprm_check(struct linux_binprm *bprm)
int ret;
u32 secid;

security_task_getsecid(current, &secid);
security_task_getsecid_subj(current, &secid);
ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0,
MAY_EXEC, BPRM_CHECK);
if (ret)
Expand All @@ -495,7 +495,7 @@ int ima_file_check(struct file *file, int mask)
{
u32 secid;

security_task_getsecid(current, &secid);
security_task_getsecid_subj(current, &secid);
return process_measurement(file, current_cred(), secid, NULL, 0,
mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
MAY_APPEND), FILE_CHECK);
Expand Down Expand Up @@ -686,7 +686,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id,

/* Read entire file for all partial reads. */
func = read_idmap[read_id] ?: FILE_CHECK;
security_task_getsecid(current, &secid);
security_task_getsecid_subj(current, &secid);
return process_measurement(file, current_cred(), secid, NULL,
0, MAY_READ, func);
}
Expand Down Expand Up @@ -729,7 +729,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
}

func = read_idmap[read_id] ?: FILE_CHECK;
security_task_getsecid(current, &secid);
security_task_getsecid_subj(current, &secid);
return process_measurement(file, current_cred(), secid, buf, size,
MAY_READ, func);
}
Expand Down Expand Up @@ -872,7 +872,7 @@ void process_buffer_measurement(struct user_namespace *mnt_userns,
* buffer measurements.
*/
if (func) {
security_task_getsecid(current, &secid);
security_task_getsecid_subj(current, &secid);
action = ima_get_action(mnt_userns, inode, current_cred(),
secid, 0, func, &pcr, &template,
func_data);
Expand Down
20 changes: 17 additions & 3 deletions security/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,13 @@ int security_sb_eat_lsm_opts(char *options, void **mnt_opts)
}
EXPORT_SYMBOL(security_sb_eat_lsm_opts);

int security_sb_mnt_opts_compat(struct super_block *sb,
void *mnt_opts)
{
return call_int_hook(sb_mnt_opts_compat, 0, sb, mnt_opts);
}
EXPORT_SYMBOL(security_sb_mnt_opts_compat);

int security_sb_remount(struct super_block *sb,
void *mnt_opts)
{
Expand Down Expand Up @@ -1762,12 +1769,19 @@ int security_task_getsid(struct task_struct *p)
return call_int_hook(task_getsid, 0, p);
}

void security_task_getsecid(struct task_struct *p, u32 *secid)
void security_task_getsecid_subj(struct task_struct *p, u32 *secid)
{
*secid = 0;
call_void_hook(task_getsecid_subj, p, secid);
}
EXPORT_SYMBOL(security_task_getsecid_subj);

void security_task_getsecid_obj(struct task_struct *p, u32 *secid)
{
*secid = 0;
call_void_hook(task_getsecid, p, secid);
call_void_hook(task_getsecid_obj, p, secid);
}
EXPORT_SYMBOL(security_task_getsecid);
EXPORT_SYMBOL(security_task_getsecid_obj);

int security_task_setnice(struct task_struct *p, int nice)
{
Expand Down
Loading

0 comments on commit f1c921f

Please sign in to comment.