selinux/stable-5.13 PR 20210426

-----BEGIN PGP SIGNATURE-----
 
 iQJIBAABCAAyFiEES0KozwfymdVUl37v6iDy2pc3iXMFAmCHM2sUHHBhdWxAcGF1
 bC1tb29yZS5jb20ACgkQ6iDy2pc3iXNfCg/9GmoCyCh+ZRj5RGQ6M+yJas1+yyJQ
 uEfTNde54yfATUTaaWYnZG59yqzM3I2uaV11U7tqg8ajiFPxJKqbs5R9jl3lnSjH
 0Dg22nXPSCOTKcU0x/DeLoKRr+M9jO1K/nQ8NEZvYX4nC/OgtCvJqb/oEQZIKAk5
 2a7OEmNNQyFGd274p9dELaDHxN9UIaJ2PzQFXtq7ROHgBXQO4ONb2ajOf6mDSFQb
 vP/CDHwaH+pcE28w44oRy0/YBkO1SrdqoFQchg5yFagM5tQRLGkXK4OFSs5KHi5Q
 YMtmaOzMPIv1e5eaC1HuuMJYA4pPb30T9hFHP7tmBVZfmZaFaDeUs+BhMm98WTiS
 o0iTP7tfs36/poOR1Q0/sB06uvF9hUAAX1ZuE95YySifbXU9hsUc9b0uQSwCdg9P
 /J9rcdHLTpWqjw9n02mezWmAvo5U8ZvbDs+0xPIwI+3RTUP5t6mp+Hd5Tc7bPTq1
 0rpWXx+FQoSytFap5qiUSiwBp+HF6HQnNIXB0Muf6wctChoTjvo7TwoxH//z4kEm
 +SddhOCNkB7VC/X7hOxhl0F/rdHuXvb1AFIWjpTLJH2CR1PvMtF+sGey+uPT6hKZ
 /gvhmQGjFdph99eGlfVbCNvx1pM61O25IscaYD1T2wGImw+z7dX4WkG3WoOdDSkR
 bRjrBkcHh0gLhWk=
 =HTEy
 -----END PGP SIGNATURE-----

Merge tag 'selinux-pr-20210426' of git://git.kernel.org/pub/scm/linux/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
This commit is contained in:
Linus Torvalds 2021-04-27 13:42:11 -07:00
commit f1c921fb70
29 changed files with 372 additions and 92 deletions

View File

@ -2713,7 +2713,16 @@ static void binder_transaction(struct binder_proc *proc,
u32 secid; u32 secid;
size_t added_size; 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); ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
if (ret) { if (ret) {
return_error = BR_FAILED_REPLY; return_error = BR_FAILED_REPLY;

View File

@ -463,6 +463,9 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
if (opt < 0) if (opt < 0)
return ctx->sloppy ? 1 : opt; return ctx->sloppy ? 1 : opt;
if (fc->security)
ctx->has_sec_mnt_opts = 1;
switch (opt) { switch (opt) {
case Opt_source: case Opt_source:
if (fc->source) if (fc->source)

View File

@ -96,6 +96,7 @@ struct nfs_fs_context {
char *fscache_uniq; char *fscache_uniq;
unsigned short protofamily; unsigned short protofamily;
unsigned short mountfamily; unsigned short mountfamily;
bool has_sec_mnt_opts;
struct { struct {
union { union {

View File

@ -1045,7 +1045,7 @@ static void nfs_fill_super(struct super_block *sb, struct nfs_fs_context *ctx)
sb->s_blocksize = 0; sb->s_blocksize = 0;
sb->s_xattr = server->nfs_client->cl_nfs_mod->xattr; sb->s_xattr = server->nfs_client->cl_nfs_mod->xattr;
sb->s_op = server->nfs_client->cl_nfs_mod->sops; 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); sb->s_blocksize = nfs_block_size(ctx->bsize, &sb->s_blocksize_bits);
if (server->nfs_client->rpc_ops->version != 2) { if (server->nfs_client->rpc_ops->version != 2) {
@ -1077,6 +1077,7 @@ static void nfs_fill_super(struct super_block *sb, struct nfs_fs_context *ctx)
&sb->s_blocksize_bits); &sb->s_blocksize_bits);
nfs_super_set_maxbytes(sb, server->maxfilesize); 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, static int nfs_compare_mount_options(const struct super_block *s, const struct nfs_server *b,
@ -1193,6 +1194,9 @@ static int nfs_compare_super(struct super_block *sb, struct fs_context *fc)
return 0; return 0;
if (!nfs_compare_userns(old, server)) if (!nfs_compare_userns(old, server))
return 0; 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); return nfs_compare_mount_options(sb, server, fc);
} }

View File

@ -140,7 +140,7 @@ struct cred {
struct key *request_key_auth; /* assumed request_key authority */ struct key *request_key_auth; /* assumed request_key authority */
#endif #endif
#ifdef CONFIG_SECURITY #ifdef CONFIG_SECURITY
void *security; /* subjective LSM security */ void *security; /* LSM security */
#endif #endif
struct user_struct *user; /* real user ID subscription */ struct user_struct *user; /* real user ID subscription */
struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */ struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */

View File

@ -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_security, struct super_block *sb)
LSM_HOOK(void, LSM_RET_VOID, sb_free_mnt_opts, void *mnt_opts) 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_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_remount, struct super_block *sb, void *mnt_opts)
LSM_HOOK(int, 0, sb_kern_mount, struct super_block *sb) 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) LSM_HOOK(int, 0, sb_show_options, struct seq_file *m, struct super_block *sb)
@ -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_setpgid, struct task_struct *p, pid_t pgid)
LSM_HOOK(int, 0, task_getpgid, struct task_struct *p) LSM_HOOK(int, 0, task_getpgid, struct task_struct *p)
LSM_HOOK(int, 0, task_getsid, 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_setnice, struct task_struct *p, int nice)
LSM_HOOK(int, 0, task_setioprio, struct task_struct *p, int ioprio) LSM_HOOK(int, 0, task_setioprio, struct task_struct *p, int ioprio)
LSM_HOOK(int, 0, task_getioprio, struct task_struct *p) LSM_HOOK(int, 0, task_getioprio, struct task_struct *p)

View File

@ -142,6 +142,12 @@
* @orig the original mount data copied from userspace. * @orig the original mount data copied from userspace.
* @copy copied data which will be passed to the security module. * @copy copied data which will be passed to the security module.
* Returns 0 if the copy was successful. * 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: * @sb_remount:
* Extracts security system specific mount options and verifies no changes * Extracts security system specific mount options and verifies no changes
* are being made to those options. * are being made to those options.
@ -707,9 +713,15 @@
* @p. * @p.
* @p contains the task_struct for the process. * @p contains the task_struct for the process.
* Return 0 if permission is granted. * Return 0 if permission is granted.
* @task_getsecid: * @task_getsecid_subj:
* Retrieve the security identifier of the process @p. * Retrieve the subjective security identifier of the task_struct in @p
* @p contains the task_struct for the process and place is into @secid. * 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. * In case of failure, @secid will be set to zero.
* *
* @task_setnice: * @task_setnice:

View File

@ -256,6 +256,7 @@ struct nfs_server {
/* User namespace info */ /* User namespace info */
const struct cred *cred; const struct cred *cred;
bool has_sec_mnt_opts;
}; };
/* Server capabilities */ /* Server capabilities */

View File

@ -294,6 +294,7 @@ int security_sb_alloc(struct super_block *sb);
void security_sb_free(struct super_block *sb); void security_sb_free(struct super_block *sb);
void security_free_mnt_opts(void **mnt_opts); void security_free_mnt_opts(void **mnt_opts);
int security_sb_eat_lsm_opts(char *options, 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_remount(struct super_block *sb, void *mnt_opts);
int security_sb_kern_mount(struct super_block *sb); int security_sb_kern_mount(struct super_block *sb);
int security_sb_show_options(struct seq_file *m, struct super_block *sb); int security_sb_show_options(struct seq_file *m, struct super_block *sb);
@ -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_setpgid(struct task_struct *p, pid_t pgid);
int security_task_getpgid(struct task_struct *p); int security_task_getpgid(struct task_struct *p);
int security_task_getsid(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_setnice(struct task_struct *p, int nice);
int security_task_setioprio(struct task_struct *p, int ioprio); int security_task_setioprio(struct task_struct *p, int ioprio);
int security_task_getioprio(struct task_struct *p); int security_task_getioprio(struct task_struct *p);
@ -646,6 +648,13 @@ static inline int security_sb_remount(struct super_block *sb,
return 0; 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) static inline int security_sb_kern_mount(struct super_block *sb)
{ {
return 0; return 0;
@ -1098,7 +1107,12 @@ static inline int security_task_getsid(struct task_struct *p)
return 0; 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; *secid = 0;
} }

View File

@ -2132,7 +2132,7 @@ int audit_log_task_context(struct audit_buffer *ab)
int error; int error;
u32 sid; u32 sid;
security_task_getsecid(current, &sid); security_task_getsecid_subj(current, &sid);
if (!sid) if (!sid)
return 0; return 0;
@ -2353,7 +2353,7 @@ int audit_signal_info(int sig, struct task_struct *t)
audit_sig_uid = auid; audit_sig_uid = auid;
else else
audit_sig_uid = uid; 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); return audit_signal_info_syscall(t);

View File

@ -1359,7 +1359,8 @@ int audit_filter(int msgtype, unsigned int listtype)
case AUDIT_SUBJ_SEN: case AUDIT_SUBJ_SEN:
case AUDIT_SUBJ_CLR: case AUDIT_SUBJ_CLR:
if (f->lsm_rule) { if (f->lsm_rule) {
security_task_getsecid(current, &sid); security_task_getsecid_subj(current,
&sid);
result = security_audit_rule_match(sid, result = security_audit_rule_match(sid,
f->type, f->op, f->lsm_rule); f->type, f->op, f->lsm_rule);
} }

View File

@ -667,7 +667,7 @@ static int audit_filter_rules(struct task_struct *tsk,
logged upon error */ logged upon error */
if (f->lsm_rule) { if (f->lsm_rule) {
if (need_sid) { if (need_sid) {
security_task_getsecid(tsk, &sid); security_task_getsecid_subj(tsk, &sid);
need_sid = 0; need_sid = 0;
} }
result = security_audit_rule_match(sid, f->type, result = security_audit_rule_match(sid, f->type,
@ -2400,7 +2400,7 @@ void __audit_ptrace(struct task_struct *t)
context->target_auid = audit_get_loginuid(t); context->target_auid = audit_get_loginuid(t);
context->target_uid = task_uid(t); context->target_uid = task_uid(t);
context->target_sessionid = audit_get_sessionid(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); memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
} }
@ -2427,7 +2427,7 @@ int audit_signal_info_syscall(struct task_struct *t)
ctx->target_auid = audit_get_loginuid(t); ctx->target_auid = audit_get_loginuid(t);
ctx->target_uid = t_uid; ctx->target_uid = t_uid;
ctx->target_sessionid = audit_get_sessionid(t); 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); memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
return 0; return 0;
} }
@ -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_auid[axp->pid_count] = audit_get_loginuid(t);
axp->target_uid[axp->pid_count] = t_uid; axp->target_uid[axp->pid_count] = t_uid;
axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t); 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); memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
axp->pid_count++; axp->pid_count++;

View File

@ -209,7 +209,8 @@ BTF_ID(func, bpf_lsm_socket_socketpair)
BTF_ID(func, bpf_lsm_syslog) BTF_ID(func, bpf_lsm_syslog)
BTF_ID(func, bpf_lsm_task_alloc) 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_prctl)
BTF_ID(func, bpf_lsm_task_setscheduler) BTF_ID(func, bpf_lsm_task_setscheduler)
BTF_ID(func, bpf_lsm_task_to_inode) BTF_ID(func, bpf_lsm_task_to_inode)

View File

@ -1539,7 +1539,7 @@ int __init netlbl_unlabel_defconf(void)
/* Only the kernel is allowed to call this function and the only time /* 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 * it is called is at bootup before the audit subsystem is reporting
* messages so don't worry to much about these values. */ * 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.loginuid = GLOBAL_ROOT_UID;
audit_info.sessionid = 0; audit_info.sessionid = 0;

View File

@ -34,7 +34,7 @@
static inline void netlbl_netlink_auditinfo(struct sk_buff *skb, static inline void netlbl_netlink_auditinfo(struct sk_buff *skb,
struct netlbl_audit *audit_info) 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->loginuid = audit_get_loginuid(current);
audit_info->sessionid = audit_get_sessionid(current); audit_info->sessionid = audit_get_sessionid(current);
} }

View File

@ -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_free, apparmor_task_free),
LSM_HOOK_INIT(task_alloc, apparmor_task_alloc), 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_setrlimit, apparmor_task_setrlimit),
LSM_HOOK_INIT(task_kill, apparmor_task_kill), LSM_HOOK_INIT(task_kill, apparmor_task_kill),

View File

@ -76,7 +76,7 @@ int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
if (!ima_appraise) if (!ima_appraise)
return 0; return 0;
security_task_getsecid(current, &secid); security_task_getsecid_subj(current, &secid);
return ima_match_policy(mnt_userns, inode, current_cred(), secid, func, return ima_match_policy(mnt_userns, inode, current_cred(), secid, func,
mask, IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL); mask, IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL);
} }

View File

@ -391,7 +391,7 @@ int ima_file_mmap(struct file *file, unsigned long prot)
u32 secid; u32 secid;
if (file && (prot & PROT_EXEC)) { if (file && (prot & PROT_EXEC)) {
security_task_getsecid(current, &secid); security_task_getsecid_subj(current, &secid);
return process_measurement(file, current_cred(), secid, NULL, return process_measurement(file, current_cred(), secid, NULL,
0, MAY_EXEC, MMAP_CHECK); 0, MAY_EXEC, MMAP_CHECK);
} }
@ -429,7 +429,7 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
!(prot & PROT_EXEC) || (vma->vm_flags & VM_EXEC)) !(prot & PROT_EXEC) || (vma->vm_flags & VM_EXEC))
return 0; return 0;
security_task_getsecid(current, &secid); security_task_getsecid_subj(current, &secid);
inode = file_inode(vma->vm_file); inode = file_inode(vma->vm_file);
action = ima_get_action(file_mnt_user_ns(vma->vm_file), inode, action = ima_get_action(file_mnt_user_ns(vma->vm_file), inode,
current_cred(), secid, MAY_EXEC, MMAP_CHECK, current_cred(), secid, MAY_EXEC, MMAP_CHECK,
@ -470,7 +470,7 @@ int ima_bprm_check(struct linux_binprm *bprm)
int ret; int ret;
u32 secid; u32 secid;
security_task_getsecid(current, &secid); security_task_getsecid_subj(current, &secid);
ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0, ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0,
MAY_EXEC, BPRM_CHECK); MAY_EXEC, BPRM_CHECK);
if (ret) if (ret)
@ -495,7 +495,7 @@ int ima_file_check(struct file *file, int mask)
{ {
u32 secid; u32 secid;
security_task_getsecid(current, &secid); security_task_getsecid_subj(current, &secid);
return process_measurement(file, current_cred(), secid, NULL, 0, return process_measurement(file, current_cred(), secid, NULL, 0,
mask & (MAY_READ | MAY_WRITE | MAY_EXEC | mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
MAY_APPEND), FILE_CHECK); MAY_APPEND), FILE_CHECK);
@ -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. */ /* Read entire file for all partial reads. */
func = read_idmap[read_id] ?: FILE_CHECK; 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, return process_measurement(file, current_cred(), secid, NULL,
0, MAY_READ, func); 0, MAY_READ, func);
} }
@ -729,7 +729,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
} }
func = read_idmap[read_id] ?: FILE_CHECK; 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, return process_measurement(file, current_cred(), secid, buf, size,
MAY_READ, func); MAY_READ, func);
} }
@ -872,7 +872,7 @@ void process_buffer_measurement(struct user_namespace *mnt_userns,
* buffer measurements. * buffer measurements.
*/ */
if (func) { if (func) {
security_task_getsecid(current, &secid); security_task_getsecid_subj(current, &secid);
action = ima_get_action(mnt_userns, inode, current_cred(), action = ima_get_action(mnt_userns, inode, current_cred(),
secid, 0, func, &pcr, &template, secid, 0, func, &pcr, &template,
func_data); func_data);

View File

@ -890,6 +890,13 @@ int security_sb_eat_lsm_opts(char *options, void **mnt_opts)
} }
EXPORT_SYMBOL(security_sb_eat_lsm_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, int security_sb_remount(struct super_block *sb,
void *mnt_opts) void *mnt_opts)
{ {
@ -1762,12 +1769,19 @@ int security_task_getsid(struct task_struct *p)
return call_int_hook(task_getsid, 0, 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; *secid = 0;
call_void_hook(task_getsecid, p, secid); call_void_hook(task_getsecid_subj, p, secid);
} }
EXPORT_SYMBOL(security_task_getsecid); EXPORT_SYMBOL(security_task_getsecid_subj);
void security_task_getsecid_obj(struct task_struct *p, u32 *secid)
{
*secid = 0;
call_void_hook(task_getsecid_obj, p, secid);
}
EXPORT_SYMBOL(security_task_getsecid_obj);
int security_task_setnice(struct task_struct *p, int nice) int security_task_setnice(struct task_struct *p, int nice)
{ {

View File

@ -229,10 +229,23 @@ static inline u32 cred_sid(const struct cred *cred)
return tsec->sid; return tsec->sid;
} }
/*
* get the subjective security ID of a task
*/
static inline u32 task_sid_subj(const struct task_struct *task)
{
u32 sid;
rcu_read_lock();
sid = cred_sid(rcu_dereference(task->cred));
rcu_read_unlock();
return sid;
}
/* /*
* get the objective security ID of a task * get the objective security ID of a task
*/ */
static inline u32 task_sid(const struct task_struct *task) static inline u32 task_sid_obj(const struct task_struct *task)
{ {
u32 sid; u32 sid;
@ -242,6 +255,29 @@ static inline u32 task_sid(const struct task_struct *task)
return sid; return sid;
} }
/*
* get the security ID of a task for use with binder
*/
static inline u32 task_sid_binder(const struct task_struct *task)
{
/*
* In many case where this function is used we should be using the
* task's subjective SID, but we can't reliably access the subjective
* creds of a task other than our own so we must use the objective
* creds/SID, 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.
*
* If this ever changes and we can safely reference the subjective
* creds/SID of another task, this function will make it easier to
* identify the various places where we make use of the task SIDs in
* the binder code. It is also likely that we will need to adjust
* the main drivers/android binder code as well.
*/
return task_sid_obj(task);
}
static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry); static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
/* /*
@ -760,7 +796,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
if (sb->s_user_ns != &init_user_ns && if (sb->s_user_ns != &init_user_ns &&
strcmp(sb->s_type->name, "tmpfs") && strcmp(sb->s_type->name, "tmpfs") &&
strcmp(sb->s_type->name, "ramfs") && strcmp(sb->s_type->name, "ramfs") &&
strcmp(sb->s_type->name, "devpts")) { strcmp(sb->s_type->name, "devpts") &&
strcmp(sb->s_type->name, "overlay")) {
if (context_sid || fscontext_sid || rootcontext_sid || if (context_sid || fscontext_sid || rootcontext_sid ||
defcontext_sid) { defcontext_sid) {
rc = -EACCES; rc = -EACCES;
@ -2034,11 +2071,8 @@ static inline u32 open_file_to_av(struct file *file)
static int selinux_binder_set_context_mgr(struct task_struct *mgr) static int selinux_binder_set_context_mgr(struct task_struct *mgr)
{ {
u32 mysid = current_sid();
u32 mgrsid = task_sid(mgr);
return avc_has_perm(&selinux_state, return avc_has_perm(&selinux_state,
mysid, mgrsid, SECCLASS_BINDER, current_sid(), task_sid_binder(mgr), SECCLASS_BINDER,
BINDER__SET_CONTEXT_MGR, NULL); BINDER__SET_CONTEXT_MGR, NULL);
} }
@ -2046,8 +2080,7 @@ static int selinux_binder_transaction(struct task_struct *from,
struct task_struct *to) struct task_struct *to)
{ {
u32 mysid = current_sid(); u32 mysid = current_sid();
u32 fromsid = task_sid(from); u32 fromsid = task_sid_binder(from);
u32 tosid = task_sid(to);
int rc; int rc;
if (mysid != fromsid) { if (mysid != fromsid) {
@ -2058,19 +2091,16 @@ static int selinux_binder_transaction(struct task_struct *from,
return rc; return rc;
} }
return avc_has_perm(&selinux_state, return avc_has_perm(&selinux_state, fromsid, task_sid_binder(to),
fromsid, tosid, SECCLASS_BINDER, BINDER__CALL, SECCLASS_BINDER, BINDER__CALL, NULL);
NULL);
} }
static int selinux_binder_transfer_binder(struct task_struct *from, static int selinux_binder_transfer_binder(struct task_struct *from,
struct task_struct *to) struct task_struct *to)
{ {
u32 fromsid = task_sid(from);
u32 tosid = task_sid(to);
return avc_has_perm(&selinux_state, return avc_has_perm(&selinux_state,
fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER, task_sid_binder(from), task_sid_binder(to),
SECCLASS_BINDER, BINDER__TRANSFER,
NULL); NULL);
} }
@ -2078,7 +2108,7 @@ static int selinux_binder_transfer_file(struct task_struct *from,
struct task_struct *to, struct task_struct *to,
struct file *file) struct file *file)
{ {
u32 sid = task_sid(to); u32 sid = task_sid_binder(to);
struct file_security_struct *fsec = selinux_file(file); struct file_security_struct *fsec = selinux_file(file);
struct dentry *dentry = file->f_path.dentry; struct dentry *dentry = file->f_path.dentry;
struct inode_security_struct *isec; struct inode_security_struct *isec;
@ -2114,10 +2144,10 @@ static int selinux_binder_transfer_file(struct task_struct *from,
} }
static int selinux_ptrace_access_check(struct task_struct *child, static int selinux_ptrace_access_check(struct task_struct *child,
unsigned int mode) unsigned int mode)
{ {
u32 sid = current_sid(); u32 sid = current_sid();
u32 csid = task_sid(child); u32 csid = task_sid_obj(child);
if (mode & PTRACE_MODE_READ) if (mode & PTRACE_MODE_READ)
return avc_has_perm(&selinux_state, return avc_has_perm(&selinux_state,
@ -2130,15 +2160,15 @@ static int selinux_ptrace_access_check(struct task_struct *child,
static int selinux_ptrace_traceme(struct task_struct *parent) static int selinux_ptrace_traceme(struct task_struct *parent)
{ {
return avc_has_perm(&selinux_state, return avc_has_perm(&selinux_state,
task_sid(parent), current_sid(), SECCLASS_PROCESS, task_sid_subj(parent), task_sid_obj(current),
PROCESS__PTRACE, NULL); SECCLASS_PROCESS, PROCESS__PTRACE, NULL);
} }
static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
kernel_cap_t *inheritable, kernel_cap_t *permitted) kernel_cap_t *inheritable, kernel_cap_t *permitted)
{ {
return avc_has_perm(&selinux_state, return avc_has_perm(&selinux_state,
current_sid(), task_sid(target), SECCLASS_PROCESS, current_sid(), task_sid_obj(target), SECCLASS_PROCESS,
PROCESS__GETCAP, NULL); PROCESS__GETCAP, NULL);
} }
@ -2263,7 +2293,7 @@ static u32 ptrace_parent_sid(void)
rcu_read_lock(); rcu_read_lock();
tracer = ptrace_parent(current); tracer = ptrace_parent(current);
if (tracer) if (tracer)
sid = task_sid(tracer); sid = task_sid_obj(tracer);
rcu_read_unlock(); rcu_read_unlock();
return sid; return sid;
@ -2684,6 +2714,61 @@ free_opt:
return rc; return rc;
} }
static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts)
{
struct selinux_mnt_opts *opts = mnt_opts;
struct superblock_security_struct *sbsec = sb->s_security;
u32 sid;
int rc;
/*
* Superblock not initialized (i.e. no options) - reject if any
* options specified, otherwise accept.
*/
if (!(sbsec->flags & SE_SBINITIALIZED))
return opts ? 1 : 0;
/*
* Superblock initialized and no options specified - reject if
* superblock has any options set, otherwise accept.
*/
if (!opts)
return (sbsec->flags & SE_MNTMASK) ? 1 : 0;
if (opts->fscontext) {
rc = parse_sid(sb, opts->fscontext, &sid);
if (rc)
return 1;
if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
return 1;
}
if (opts->context) {
rc = parse_sid(sb, opts->context, &sid);
if (rc)
return 1;
if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
return 1;
}
if (opts->rootcontext) {
struct inode_security_struct *root_isec;
root_isec = backing_inode_security(sb->s_root);
rc = parse_sid(sb, opts->rootcontext, &sid);
if (rc)
return 1;
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
return 1;
}
if (opts->defcontext) {
rc = parse_sid(sb, opts->defcontext, &sid);
if (rc)
return 1;
if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
return 1;
}
return 0;
}
static int selinux_sb_remount(struct super_block *sb, void *mnt_opts) static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
{ {
struct selinux_mnt_opts *opts = mnt_opts; struct selinux_mnt_opts *opts = mnt_opts;
@ -3920,7 +4005,7 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
struct fown_struct *fown, int signum) struct fown_struct *fown, int signum)
{ {
struct file *file; struct file *file;
u32 sid = task_sid(tsk); u32 sid = task_sid_obj(tsk);
u32 perm; u32 perm;
struct file_security_struct *fsec; struct file_security_struct *fsec;
@ -4139,47 +4224,52 @@ static int selinux_kernel_load_data(enum kernel_load_data_id id, bool contents)
static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
{ {
return avc_has_perm(&selinux_state, return avc_has_perm(&selinux_state,
current_sid(), task_sid(p), SECCLASS_PROCESS, current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
PROCESS__SETPGID, NULL); PROCESS__SETPGID, NULL);
} }
static int selinux_task_getpgid(struct task_struct *p) static int selinux_task_getpgid(struct task_struct *p)
{ {
return avc_has_perm(&selinux_state, return avc_has_perm(&selinux_state,
current_sid(), task_sid(p), SECCLASS_PROCESS, current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
PROCESS__GETPGID, NULL); PROCESS__GETPGID, NULL);
} }
static int selinux_task_getsid(struct task_struct *p) static int selinux_task_getsid(struct task_struct *p)
{ {
return avc_has_perm(&selinux_state, return avc_has_perm(&selinux_state,
current_sid(), task_sid(p), SECCLASS_PROCESS, current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
PROCESS__GETSESSION, NULL); PROCESS__GETSESSION, NULL);
} }
static void selinux_task_getsecid(struct task_struct *p, u32 *secid) static void selinux_task_getsecid_subj(struct task_struct *p, u32 *secid)
{ {
*secid = task_sid(p); *secid = task_sid_subj(p);
}
static void selinux_task_getsecid_obj(struct task_struct *p, u32 *secid)
{
*secid = task_sid_obj(p);
} }
static int selinux_task_setnice(struct task_struct *p, int nice) static int selinux_task_setnice(struct task_struct *p, int nice)
{ {
return avc_has_perm(&selinux_state, return avc_has_perm(&selinux_state,
current_sid(), task_sid(p), SECCLASS_PROCESS, current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
PROCESS__SETSCHED, NULL); PROCESS__SETSCHED, NULL);
} }
static int selinux_task_setioprio(struct task_struct *p, int ioprio) static int selinux_task_setioprio(struct task_struct *p, int ioprio)
{ {
return avc_has_perm(&selinux_state, return avc_has_perm(&selinux_state,
current_sid(), task_sid(p), SECCLASS_PROCESS, current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
PROCESS__SETSCHED, NULL); PROCESS__SETSCHED, NULL);
} }
static int selinux_task_getioprio(struct task_struct *p) static int selinux_task_getioprio(struct task_struct *p)
{ {
return avc_has_perm(&selinux_state, return avc_has_perm(&selinux_state,
current_sid(), task_sid(p), SECCLASS_PROCESS, current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
PROCESS__GETSCHED, NULL); PROCESS__GETSCHED, NULL);
} }
@ -4210,7 +4300,7 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
upon context transitions. See selinux_bprm_committing_creds. */ upon context transitions. See selinux_bprm_committing_creds. */
if (old_rlim->rlim_max != new_rlim->rlim_max) if (old_rlim->rlim_max != new_rlim->rlim_max)
return avc_has_perm(&selinux_state, return avc_has_perm(&selinux_state,
current_sid(), task_sid(p), current_sid(), task_sid_obj(p),
SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL); SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL);
return 0; return 0;
@ -4219,21 +4309,21 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
static int selinux_task_setscheduler(struct task_struct *p) static int selinux_task_setscheduler(struct task_struct *p)
{ {
return avc_has_perm(&selinux_state, return avc_has_perm(&selinux_state,
current_sid(), task_sid(p), SECCLASS_PROCESS, current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
PROCESS__SETSCHED, NULL); PROCESS__SETSCHED, NULL);
} }
static int selinux_task_getscheduler(struct task_struct *p) static int selinux_task_getscheduler(struct task_struct *p)
{ {
return avc_has_perm(&selinux_state, return avc_has_perm(&selinux_state,
current_sid(), task_sid(p), SECCLASS_PROCESS, current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
PROCESS__GETSCHED, NULL); PROCESS__GETSCHED, NULL);
} }
static int selinux_task_movememory(struct task_struct *p) static int selinux_task_movememory(struct task_struct *p)
{ {
return avc_has_perm(&selinux_state, return avc_has_perm(&selinux_state,
current_sid(), task_sid(p), SECCLASS_PROCESS, current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
PROCESS__SETSCHED, NULL); PROCESS__SETSCHED, NULL);
} }
@ -4252,14 +4342,14 @@ static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info,
else else
secid = cred_sid(cred); secid = cred_sid(cred);
return avc_has_perm(&selinux_state, return avc_has_perm(&selinux_state,
secid, task_sid(p), SECCLASS_PROCESS, perm, NULL); secid, task_sid_obj(p), SECCLASS_PROCESS, perm, NULL);
} }
static void selinux_task_to_inode(struct task_struct *p, static void selinux_task_to_inode(struct task_struct *p,
struct inode *inode) struct inode *inode)
{ {
struct inode_security_struct *isec = selinux_inode(inode); struct inode_security_struct *isec = selinux_inode(inode);
u32 sid = task_sid(p); u32 sid = task_sid_obj(p);
spin_lock(&isec->lock); spin_lock(&isec->lock);
isec->sclass = inode_mode_to_security_class(inode->i_mode); isec->sclass = inode_mode_to_security_class(inode->i_mode);
@ -6152,7 +6242,7 @@ static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *m
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct msg_security_struct *msec; struct msg_security_struct *msec;
struct common_audit_data ad; struct common_audit_data ad;
u32 sid = task_sid(target); u32 sid = task_sid_subj(target);
int rc; int rc;
isec = selinux_ipc(msq); isec = selinux_ipc(msq);
@ -7077,6 +7167,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security), LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
LSM_HOOK_INIT(sb_free_mnt_opts, selinux_free_mnt_opts), LSM_HOOK_INIT(sb_free_mnt_opts, selinux_free_mnt_opts),
LSM_HOOK_INIT(sb_mnt_opts_compat, selinux_sb_mnt_opts_compat),
LSM_HOOK_INIT(sb_remount, selinux_sb_remount), LSM_HOOK_INIT(sb_remount, selinux_sb_remount),
LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount), LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount),
LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options), LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),
@ -7148,7 +7239,8 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid), LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid), LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
LSM_HOOK_INIT(task_getsid, selinux_task_getsid), LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
LSM_HOOK_INIT(task_getsecid, selinux_task_getsecid), LSM_HOOK_INIT(task_getsecid_subj, selinux_task_getsecid_subj),
LSM_HOOK_INIT(task_getsecid_obj, selinux_task_getsecid_obj),
LSM_HOOK_INIT(task_setnice, selinux_task_setnice), LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio), LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio), LSM_HOOK_INIT(task_getioprio, selinux_task_getioprio),

View File

@ -13,18 +13,83 @@
#include "ima.h" #include "ima.h"
/* /*
* selinux_ima_measure_state - Measure hash of the SELinux policy * selinux_ima_collect_state - Read selinux configuration settings
*
* @state: selinux_state
*
* On success returns the configuration settings string.
* On error, returns NULL.
*/
static char *selinux_ima_collect_state(struct selinux_state *state)
{
const char *on = "=1;", *off = "=0;";
char *buf;
int buf_len, len, i, rc;
buf_len = strlen("initialized=0;enforcing=0;checkreqprot=0;") + 1;
len = strlen(on);
for (i = 0; i < __POLICYDB_CAPABILITY_MAX; i++)
buf_len += strlen(selinux_policycap_names[i]) + len;
buf = kzalloc(buf_len, GFP_KERNEL);
if (!buf)
return NULL;
rc = strscpy(buf, "initialized", buf_len);
WARN_ON(rc < 0);
rc = strlcat(buf, selinux_initialized(state) ? on : off, buf_len);
WARN_ON(rc >= buf_len);
rc = strlcat(buf, "enforcing", buf_len);
WARN_ON(rc >= buf_len);
rc = strlcat(buf, enforcing_enabled(state) ? on : off, buf_len);
WARN_ON(rc >= buf_len);
rc = strlcat(buf, "checkreqprot", buf_len);
WARN_ON(rc >= buf_len);
rc = strlcat(buf, checkreqprot_get(state) ? on : off, buf_len);
WARN_ON(rc >= buf_len);
for (i = 0; i < __POLICYDB_CAPABILITY_MAX; i++) {
rc = strlcat(buf, selinux_policycap_names[i], buf_len);
WARN_ON(rc >= buf_len);
rc = strlcat(buf, state->policycap[i] ? on : off, buf_len);
WARN_ON(rc >= buf_len);
}
return buf;
}
/*
* selinux_ima_measure_state_locked - Measure SELinux state and hash of policy
* *
* @state: selinux state struct * @state: selinux state struct
*
* NOTE: This function must be called with policy_mutex held.
*/ */
void selinux_ima_measure_state(struct selinux_state *state) void selinux_ima_measure_state_locked(struct selinux_state *state)
{ {
char *state_str = NULL;
void *policy = NULL; void *policy = NULL;
size_t policy_len; size_t policy_len;
int rc = 0; int rc = 0;
WARN_ON(!mutex_is_locked(&state->policy_mutex));
state_str = selinux_ima_collect_state(state);
if (!state_str) {
pr_err("SELinux: %s: failed to read state.\n", __func__);
return;
}
ima_measure_critical_data("selinux", "selinux-state",
state_str, strlen(state_str), false);
kfree(state_str);
/* /*
* Measure SELinux policy only after initialization is completed. * Measure SELinux policy only after initialization is completed.
*/ */
@ -42,3 +107,17 @@ void selinux_ima_measure_state(struct selinux_state *state)
vfree(policy); vfree(policy);
} }
/*
* selinux_ima_measure_state - Measure SELinux state and hash of policy
*
* @state: selinux state struct
*/
void selinux_ima_measure_state(struct selinux_state *state)
{
WARN_ON(mutex_is_locked(&state->policy_mutex));
mutex_lock(&state->policy_mutex);
selinux_ima_measure_state_locked(state);
mutex_unlock(&state->policy_mutex);
}

View File

@ -242,11 +242,12 @@ struct security_class_mapping secclass_map[] = {
{ "infiniband_endport", { "infiniband_endport",
{ "manage_subnet", NULL } }, { "manage_subnet", NULL } },
{ "bpf", { "bpf",
{"map_create", "map_read", "map_write", "prog_load", "prog_run"} }, { "map_create", "map_read", "map_write", "prog_load", "prog_run",
NULL } },
{ "xdp_socket", { "xdp_socket",
{ COMMON_SOCK_PERMS, NULL } }, { COMMON_SOCK_PERMS, NULL } },
{ "perf_event", { "perf_event",
{"open", "cpu", "kernel", "tracepoint", "read", "write"} }, { "open", "cpu", "kernel", "tracepoint", "read", "write", NULL } },
{ "lockdown", { "lockdown",
{ "integrity", "confidentiality", NULL } }, { "integrity", "confidentiality", NULL } },
{ "anon_inode", { "anon_inode",

View File

@ -15,10 +15,16 @@
#ifdef CONFIG_IMA #ifdef CONFIG_IMA
extern void selinux_ima_measure_state(struct selinux_state *selinux_state); extern void selinux_ima_measure_state(struct selinux_state *selinux_state);
extern void selinux_ima_measure_state_locked(
struct selinux_state *selinux_state);
#else #else
static inline void selinux_ima_measure_state(struct selinux_state *selinux_state) static inline void selinux_ima_measure_state(struct selinux_state *selinux_state)
{ {
} }
static inline void selinux_ima_measure_state_locked(
struct selinux_state *selinux_state)
{
}
#endif #endif
#endif /* _SELINUX_IMA_H_ */ #endif /* _SELINUX_IMA_H_ */

View File

@ -426,7 +426,7 @@ extern struct page *selinux_kernel_status_page(struct selinux_state *state);
#define SELINUX_KERNEL_STATUS_VERSION 1 #define SELINUX_KERNEL_STATUS_VERSION 1
struct selinux_kernel_status { struct selinux_kernel_status {
u32 version; /* version number of thie structure */ u32 version; /* version number of the structure */
u32 sequence; /* sequence number of seqlock logic */ u32 sequence; /* sequence number of seqlock logic */
u32 enforcing; /* current setting of enforcing mode */ u32 enforcing; /* current setting of enforcing mode */
u32 policyload; /* times of policy reloaded */ u32 policyload; /* times of policy reloaded */

View File

@ -41,6 +41,7 @@
#include "security.h" #include "security.h"
#include "objsec.h" #include "objsec.h"
#include "conditional.h" #include "conditional.h"
#include "ima.h"
enum sel_inos { enum sel_inos {
SEL_ROOT_INO = 2, SEL_ROOT_INO = 2,
@ -182,6 +183,8 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
selinux_status_update_setenforce(state, new_value); selinux_status_update_setenforce(state, new_value);
if (!new_value) if (!new_value)
call_blocking_lsm_notifier(LSM_POLICY_CHANGE, NULL); call_blocking_lsm_notifier(LSM_POLICY_CHANGE, NULL);
selinux_ima_measure_state(state);
} }
length = count; length = count;
out: out:
@ -758,6 +761,9 @@ static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
checkreqprot_set(fsi->state, (new_value ? 1 : 0)); checkreqprot_set(fsi->state, (new_value ? 1 : 0));
length = count; length = count;
selinux_ima_measure_state(fsi->state);
out: out:
kfree(page); kfree(page);
return length; return length;

View File

@ -13,7 +13,7 @@ static struct kmem_cache *hashtab_node_cachep __ro_after_init;
/* /*
* Here we simply round the number of elements up to the nearest power of two. * Here we simply round the number of elements up to the nearest power of two.
* I tried also other options like rouding down or rounding to the closest * I tried also other options like rounding down or rounding to the closest
* power of two (up or down based on which is closer), but I was unable to * power of two (up or down based on which is closer), but I was unable to
* find any significant difference in lookup/insert performance that would * find any significant difference in lookup/insert performance that would
* justify switching to a different (less intuitive) formula. It could be that * justify switching to a different (less intuitive) formula. It could be that

View File

@ -2202,7 +2202,7 @@ static void selinux_notify_policy_change(struct selinux_state *state,
selinux_status_update_policyload(state, seqno); selinux_status_update_policyload(state, seqno);
selinux_netlbl_cache_invalidate(); selinux_netlbl_cache_invalidate();
selinux_xfrm_notify_policyload(); selinux_xfrm_notify_policyload();
selinux_ima_measure_state(state); selinux_ima_measure_state_locked(state);
} }
void selinux_policy_commit(struct selinux_state *state, void selinux_policy_commit(struct selinux_state *state,

View File

@ -383,7 +383,23 @@ static inline struct smack_known *smk_of_task(const struct task_smack *tsp)
return tsp->smk_task; return tsp->smk_task;
} }
static inline struct smack_known *smk_of_task_struct( static inline struct smack_known *smk_of_task_struct_subj(
const struct task_struct *t)
{
struct smack_known *skp;
const struct cred *cred;
rcu_read_lock();
cred = rcu_dereference(t->cred);
skp = smk_of_task(smack_cred(cred));
rcu_read_unlock();
return skp;
}
static inline struct smack_known *smk_of_task_struct_obj(
const struct task_struct *t) const struct task_struct *t)
{ {
struct smack_known *skp; struct smack_known *skp;

View File

@ -159,7 +159,7 @@ static int smk_bu_current(char *note, struct smack_known *oskp,
static int smk_bu_task(struct task_struct *otp, int mode, int rc) static int smk_bu_task(struct task_struct *otp, int mode, int rc)
{ {
struct task_smack *tsp = smack_cred(current_cred()); struct task_smack *tsp = smack_cred(current_cred());
struct smack_known *smk_task = smk_of_task_struct(otp); struct smack_known *smk_task = smk_of_task_struct_obj(otp);
char acc[SMK_NUM_ACCESS_TYPE + 1]; char acc[SMK_NUM_ACCESS_TYPE + 1];
if (rc <= 0) if (rc <= 0)
@ -479,7 +479,7 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
{ {
struct smack_known *skp; struct smack_known *skp;
skp = smk_of_task_struct(ctp); skp = smk_of_task_struct_obj(ctp);
return smk_ptrace_rule_check(current, skp, mode, __func__); return smk_ptrace_rule_check(current, skp, mode, __func__);
} }
@ -2033,7 +2033,7 @@ static int smk_curacc_on_task(struct task_struct *p, int access,
const char *caller) const char *caller)
{ {
struct smk_audit_info ad; struct smk_audit_info ad;
struct smack_known *skp = smk_of_task_struct(p); struct smack_known *skp = smk_of_task_struct_subj(p);
int rc; int rc;
smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK); smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK);
@ -2078,15 +2078,29 @@ static int smack_task_getsid(struct task_struct *p)
} }
/** /**
* smack_task_getsecid - get the secid of the task * smack_task_getsecid_subj - get the subjective secid of the task
* @p: the object task * @p: the task
* @secid: where to put the result * @secid: where to put the result
* *
* Sets the secid to contain a u32 version of the smack label. * Sets the secid to contain a u32 version of the task's subjective smack label.
*/ */
static void smack_task_getsecid(struct task_struct *p, u32 *secid) static void smack_task_getsecid_subj(struct task_struct *p, u32 *secid)
{ {
struct smack_known *skp = smk_of_task_struct(p); struct smack_known *skp = smk_of_task_struct_subj(p);
*secid = skp->smk_secid;
}
/**
* smack_task_getsecid_obj - get the objective secid of the task
* @p: the task
* @secid: where to put the result
*
* Sets the secid to contain a u32 version of the task's objective smack label.
*/
static void smack_task_getsecid_obj(struct task_struct *p, u32 *secid)
{
struct smack_known *skp = smk_of_task_struct_obj(p);
*secid = skp->smk_secid; *secid = skp->smk_secid;
} }
@ -2174,7 +2188,7 @@ static int smack_task_kill(struct task_struct *p, struct kernel_siginfo *info,
{ {
struct smk_audit_info ad; struct smk_audit_info ad;
struct smack_known *skp; struct smack_known *skp;
struct smack_known *tkp = smk_of_task_struct(p); struct smack_known *tkp = smk_of_task_struct_obj(p);
int rc; int rc;
if (!sig) if (!sig)
@ -2212,7 +2226,7 @@ static int smack_task_kill(struct task_struct *p, struct kernel_siginfo *info,
static void smack_task_to_inode(struct task_struct *p, struct inode *inode) static void smack_task_to_inode(struct task_struct *p, struct inode *inode)
{ {
struct inode_smack *isp = smack_inode(inode); struct inode_smack *isp = smack_inode(inode);
struct smack_known *skp = smk_of_task_struct(p); struct smack_known *skp = smk_of_task_struct_obj(p);
isp->smk_inode = skp; isp->smk_inode = skp;
isp->smk_flags |= SMK_INODE_INSTANT; isp->smk_flags |= SMK_INODE_INSTANT;
@ -3483,7 +3497,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
*/ */
static int smack_getprocattr(struct task_struct *p, char *name, char **value) static int smack_getprocattr(struct task_struct *p, char *name, char **value)
{ {
struct smack_known *skp = smk_of_task_struct(p); struct smack_known *skp = smk_of_task_struct_subj(p);
char *cp; char *cp;
int slen; int slen;
@ -4759,7 +4773,8 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(task_setpgid, smack_task_setpgid), LSM_HOOK_INIT(task_setpgid, smack_task_setpgid),
LSM_HOOK_INIT(task_getpgid, smack_task_getpgid), LSM_HOOK_INIT(task_getpgid, smack_task_getpgid),
LSM_HOOK_INIT(task_getsid, smack_task_getsid), LSM_HOOK_INIT(task_getsid, smack_task_getsid),
LSM_HOOK_INIT(task_getsecid, smack_task_getsecid), LSM_HOOK_INIT(task_getsecid_subj, smack_task_getsecid_subj),
LSM_HOOK_INIT(task_getsecid_obj, smack_task_getsecid_obj),
LSM_HOOK_INIT(task_setnice, smack_task_setnice), LSM_HOOK_INIT(task_setnice, smack_task_setnice),
LSM_HOOK_INIT(task_setioprio, smack_task_setioprio), LSM_HOOK_INIT(task_setioprio, smack_task_setioprio),
LSM_HOOK_INIT(task_getioprio, smack_task_getioprio), LSM_HOOK_INIT(task_getioprio, smack_task_getioprio),