Commit cdab10bf authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'selinux-pr-20211101' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux

Pull selinux updates from Paul Moore:

 - Add LSM/SELinux/Smack controls and auditing for io-uring.

   As usual, the individual commit descriptions have more detail, but we
   were basically missing two things which we're adding here:

      + establishment of a proper audit context so that auditing of
        io-uring ops works similarly to how it does for syscalls (with
        some io-uring additions because io-uring ops are *not* syscalls)

      + additional LSM hooks to enable access control points for some of
        the more unusual io-uring features, e.g. credential overrides.

   The additional audit callouts and LSM hooks were done in conjunction
   with the io-uring folks, based on conversations and RFC patches
   earlier in the year.

 - Fixup the binder credential handling so that the proper credentials
   are used in the LSM hooks; the commit description and the code
   comment which is removed in these patches are helpful to understand
   the background and why this is the proper fix.

 - Enable SELinux genfscon policy support for securityfs, allowing
   improved SELinux filesystem labeling for other subsystems which make
   use of securityfs, e.g. IMA.

* tag 'selinux-pr-20211101' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux:
  security: Return xattr name from security_dentry_init_security()
  selinux: fix a sock regression in selinux_ip_postroute_compat()
  binder: use cred instead of task for getsecid
  binder: use cred instead of task for selinux checks
  binder: use euid from cred instead of using task
  LSM: Avoid warnings about potentially unused hook variables
  selinux: fix all of the W=1 build warnings
  selinux: make better use of the nf_hook_state passed to the NF hooks
  selinux: fix race condition when computing ocontext SIDs
  selinux: remove unneeded ipv6 hook wrappers
  selinux: remove the SELinux lockdown implementation
  selinux: enable genfscon labeling for securityfs
  Smack: Brutalist io_uring support
  selinux: add support for the io_uring access controls
  lsm,io_uring: add LSM hooks to io_uring
  io_uring: convert io_uring to the secure anon inode interface
  fs: add anon_inode_getfile_secure() similar to anon_inode_getfd_secure()
  audit: add filtering for io_uring records
  audit,io_uring,io-wq: add some basic audit support to io_uring
  audit: prepare audit_context for use in calling contexts beyond syscalls
parents 6fedc280 15bf3239
......@@ -2056,7 +2056,7 @@ static int binder_translate_binder(struct flat_binder_object *fp,
ret = -EINVAL;
goto done;
}
if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) {
if (security_binder_transfer_binder(proc->cred, target_proc->cred)) {
ret = -EPERM;
goto done;
}
......@@ -2102,7 +2102,7 @@ static int binder_translate_handle(struct flat_binder_object *fp,
proc->pid, thread->pid, fp->handle);
return -EINVAL;
}
if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) {
if (security_binder_transfer_binder(proc->cred, target_proc->cred)) {
ret = -EPERM;
goto done;
}
......@@ -2190,7 +2190,7 @@ static int binder_translate_fd(u32 fd, binder_size_t fd_offset,
ret = -EBADF;
goto err_fget;
}
ret = security_binder_transfer_file(proc->tsk, target_proc->tsk, file);
ret = security_binder_transfer_file(proc->cred, target_proc->cred, file);
if (ret < 0) {
ret = -EPERM;
goto err_security;
......@@ -2595,8 +2595,8 @@ static void binder_transaction(struct binder_proc *proc,
return_error_line = __LINE__;
goto err_invalid_target_handle;
}
if (security_binder_transaction(proc->tsk,
target_proc->tsk) < 0) {
if (security_binder_transaction(proc->cred,
target_proc->cred) < 0) {
return_error = BR_FAILED_REPLY;
return_error_param = -EPERM;
return_error_line = __LINE__;
......@@ -2711,7 +2711,7 @@ static void binder_transaction(struct binder_proc *proc,
t->from = thread;
else
t->from = NULL;
t->sender_euid = task_euid(proc->tsk);
t->sender_euid = proc->cred->euid;
t->to_proc = target_proc;
t->to_thread = target_thread;
t->code = tr->code;
......@@ -2722,16 +2722,7 @@ static void binder_transaction(struct binder_proc *proc,
u32 secid;
size_t added_size;
/*
* 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);
security_cred_getsecid(proc->cred, &secid);
ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
if (ret) {
return_error = BR_FAILED_REPLY;
......@@ -4353,6 +4344,7 @@ static void binder_free_proc(struct binder_proc *proc)
}
binder_alloc_deferred_release(&proc->alloc);
put_task_struct(proc->tsk);
put_cred(proc->cred);
binder_stats_deleted(BINDER_STAT_PROC);
kfree(proc);
}
......@@ -4564,7 +4556,7 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp,
ret = -EBUSY;
goto out;
}
ret = security_binder_set_context_mgr(proc->tsk);
ret = security_binder_set_context_mgr(proc->cred);
if (ret < 0)
goto out;
if (uid_valid(context->binder_context_mgr_uid)) {
......@@ -5055,6 +5047,7 @@ static int binder_open(struct inode *nodp, struct file *filp)
spin_lock_init(&proc->outer_lock);
get_task_struct(current->group_leader);
proc->tsk = current->group_leader;
proc->cred = get_cred(filp->f_cred);
INIT_LIST_HEAD(&proc->todo);
init_waitqueue_head(&proc->freeze_wait);
proc->default_priority = task_nice(current);
......
......@@ -364,6 +364,9 @@ struct binder_ref {
* (invariant after initialized)
* @tsk task_struct for group_leader of process
* (invariant after initialized)
* @cred struct cred associated with the `struct file`
* in binder_open()
* (invariant after initialized)
* @deferred_work_node: element for binder_deferred_list
* (protected by binder_deferred_lock)
* @deferred_work: bitmap of deferred work to perform
......@@ -426,6 +429,7 @@ struct binder_proc {
struct list_head waiting_threads;
int pid;
struct task_struct *tsk;
const struct cred *cred;
struct hlist_node deferred_work_node;
int deferred_work;
int outstanding_txns;
......
......@@ -148,6 +148,35 @@ struct file *anon_inode_getfile(const char *name,
}
EXPORT_SYMBOL_GPL(anon_inode_getfile);
/**
* anon_inode_getfile_secure - Like anon_inode_getfile(), but creates a new
* !S_PRIVATE anon inode rather than reuse the
* singleton anon inode and calls the
* inode_init_security_anon() LSM hook. This
* allows for both the inode to have its own
* security context and for the LSM to enforce
* policy on the inode's creation.
*
* @name: [in] name of the "class" of the new file
* @fops: [in] file operations for the new file
* @priv: [in] private data for the new file (will be file's private_data)
* @flags: [in] flags
* @context_inode:
* [in] the logical relationship with the new inode (optional)
*
* The LSM may use @context_inode in inode_init_security_anon(), but a
* reference to it is not held. Returns the newly created file* or an error
* pointer. See the anon_inode_getfile() documentation for more information.
*/
struct file *anon_inode_getfile_secure(const char *name,
const struct file_operations *fops,
void *priv, int flags,
const struct inode *context_inode)
{
return __anon_inode_getfile(name, fops, priv, flags,
context_inode, true);
}
static int __anon_inode_getfd(const char *name,
const struct file_operations *fops,
void *priv, int flags,
......
......@@ -1311,7 +1311,7 @@ int ceph_security_init_secctx(struct dentry *dentry, umode_t mode,
int err;
err = security_dentry_init_security(dentry, mode, &dentry->d_name,
&as_ctx->sec_ctx,
&name, &as_ctx->sec_ctx,
&as_ctx->sec_ctxlen);
if (err < 0) {
WARN_ON_ONCE(err != -EOPNOTSUPP);
......@@ -1335,7 +1335,6 @@ int ceph_security_init_secctx(struct dentry *dentry, umode_t mode,
* It only supports single security module and only selinux has
* dentry_init_security hook.
*/
name = XATTR_NAME_SELINUX;
name_len = strlen(name);
err = ceph_pagelist_reserve(pagelist,
4 * 2 + name_len + as_ctx->sec_ctxlen);
......
......@@ -14,6 +14,7 @@
#include <linux/rculist_nulls.h>
#include <linux/cpu.h>
#include <linux/tracehook.h>
#include <linux/audit.h>
#include <uapi/linux/io_uring.h>
#include "io-wq.h"
......@@ -593,6 +594,8 @@ static int io_wqe_worker(void *data)
snprintf(buf, sizeof(buf), "iou-wrk-%d", wq->task->pid);
set_task_comm(current, buf);
audit_alloc_kernel(current);
while (!test_bit(IO_WQ_BIT_EXIT, &wq->state)) {
long ret;
......@@ -631,6 +634,7 @@ static int io_wqe_worker(void *data)
io_worker_handle_work(worker);
}
audit_free(current);
io_worker_exit(worker);
return 0;
}
......
......@@ -79,6 +79,8 @@
#include <linux/pagemap.h>
#include <linux/io_uring.h>
#include <linux/tracehook.h>
#include <linux/audit.h>
#include <linux/security.h>
#define CREATE_TRACE_POINTS
#include <trace/events/io_uring.h>
......@@ -912,6 +914,8 @@ struct io_op_def {
unsigned needs_async_setup : 1;
/* opcode is not supported by this kernel */
unsigned not_supported : 1;
/* skip auditing */
unsigned audit_skip : 1;
/* size of async data needed, if any */
unsigned short async_size;
};
......@@ -925,6 +929,7 @@ static const struct io_op_def io_op_defs[] = {
.buffer_select = 1,
.needs_async_setup = 1,
.plug = 1,
.audit_skip = 1,
.async_size = sizeof(struct io_async_rw),
},
[IORING_OP_WRITEV] = {
......@@ -934,16 +939,19 @@ static const struct io_op_def io_op_defs[] = {
.pollout = 1,
.needs_async_setup = 1,
.plug = 1,
.audit_skip = 1,
.async_size = sizeof(struct io_async_rw),
},
[IORING_OP_FSYNC] = {
.needs_file = 1,
.audit_skip = 1,
},
[IORING_OP_READ_FIXED] = {
.needs_file = 1,
.unbound_nonreg_file = 1,
.pollin = 1,
.plug = 1,
.audit_skip = 1,
.async_size = sizeof(struct io_async_rw),
},
[IORING_OP_WRITE_FIXED] = {
......@@ -952,15 +960,20 @@ static const struct io_op_def io_op_defs[] = {
.unbound_nonreg_file = 1,
.pollout = 1,
.plug = 1,
.audit_skip = 1,
.async_size = sizeof(struct io_async_rw),
},
[IORING_OP_POLL_ADD] = {
.needs_file = 1,
.unbound_nonreg_file = 1,
.audit_skip = 1,
},
[IORING_OP_POLL_REMOVE] = {
.audit_skip = 1,
},
[IORING_OP_POLL_REMOVE] = {},
[IORING_OP_SYNC_FILE_RANGE] = {
.needs_file = 1,
.audit_skip = 1,
},
[IORING_OP_SENDMSG] = {
.needs_file = 1,
......@@ -978,18 +991,23 @@ static const struct io_op_def io_op_defs[] = {
.async_size = sizeof(struct io_async_msghdr),
},
[IORING_OP_TIMEOUT] = {
.audit_skip = 1,
.async_size = sizeof(struct io_timeout_data),
},
[IORING_OP_TIMEOUT_REMOVE] = {
/* used by timeout updates' prep() */
.audit_skip = 1,
},
[IORING_OP_ACCEPT] = {
.needs_file = 1,
.unbound_nonreg_file = 1,
.pollin = 1,
},
[IORING_OP_ASYNC_CANCEL] = {},
[IORING_OP_ASYNC_CANCEL] = {
.audit_skip = 1,
},
[IORING_OP_LINK_TIMEOUT] = {
.audit_skip = 1,
.async_size = sizeof(struct io_timeout_data),
},
[IORING_OP_CONNECT] = {
......@@ -1004,14 +1022,19 @@ static const struct io_op_def io_op_defs[] = {
},
[IORING_OP_OPENAT] = {},
[IORING_OP_CLOSE] = {},
[IORING_OP_FILES_UPDATE] = {},
[IORING_OP_STATX] = {},
[IORING_OP_FILES_UPDATE] = {
.audit_skip = 1,
},
[IORING_OP_STATX] = {
.audit_skip = 1,
},
[IORING_OP_READ] = {
.needs_file = 1,
.unbound_nonreg_file = 1,
.pollin = 1,
.buffer_select = 1,
.plug = 1,
.audit_skip = 1,
.async_size = sizeof(struct io_async_rw),
},
[IORING_OP_WRITE] = {
......@@ -1020,39 +1043,50 @@ static const struct io_op_def io_op_defs[] = {
.unbound_nonreg_file = 1,
.pollout = 1,
.plug = 1,
.audit_skip = 1,
.async_size = sizeof(struct io_async_rw),
},
[IORING_OP_FADVISE] = {
.needs_file = 1,
.audit_skip = 1,
},
[IORING_OP_MADVISE] = {},
[IORING_OP_SEND] = {
.needs_file = 1,
.unbound_nonreg_file = 1,
.pollout = 1,
.audit_skip = 1,
},
[IORING_OP_RECV] = {
.needs_file = 1,
.unbound_nonreg_file = 1,
.pollin = 1,
.buffer_select = 1,
.audit_skip = 1,
},
[IORING_OP_OPENAT2] = {
},
[IORING_OP_EPOLL_CTL] = {
.unbound_nonreg_file = 1,
.audit_skip = 1,
},
[IORING_OP_SPLICE] = {
.needs_file = 1,
.hash_reg_file = 1,
.unbound_nonreg_file = 1,
.audit_skip = 1,
},
[IORING_OP_PROVIDE_BUFFERS] = {
.audit_skip = 1,
},
[IORING_OP_REMOVE_BUFFERS] = {
.audit_skip = 1,
},
[IORING_OP_PROVIDE_BUFFERS] = {},
[IORING_OP_REMOVE_BUFFERS] = {},
[IORING_OP_TEE] = {
.needs_file = 1,
.hash_reg_file = 1,
.unbound_nonreg_file = 1,
.audit_skip = 1,
},
[IORING_OP_SHUTDOWN] = {
.needs_file = 1,
......@@ -6581,6 +6615,9 @@ static int io_issue_sqe(struct io_kiocb *req, unsigned int issue_flags)
if (unlikely((req->flags & REQ_F_CREDS) && req->creds != current_cred()))
creds = override_creds(req->creds);
if (!io_op_defs[req->opcode].audit_skip)
audit_uring_entry(req->opcode);
switch (req->opcode) {
case IORING_OP_NOP:
ret = io_nop(req, issue_flags);
......@@ -6696,6 +6733,9 @@ static int io_issue_sqe(struct io_kiocb *req, unsigned int issue_flags)
break;
}
if (!io_op_defs[req->opcode].audit_skip)
audit_uring_exit(!ret, ret);
if (creds)
revert_creds(creds);
if (ret)
......@@ -7090,10 +7130,17 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
personality = READ_ONCE(sqe->personality);
if (personality) {
int ret;
req->creds = xa_load(&ctx->personalities, personality);
if (!req->creds)
return -EINVAL;
get_cred(req->creds);
ret = security_uring_override_creds(req->creds);
if (ret) {
put_cred(req->creds);
return ret;
}
req->flags |= REQ_F_CREDS;
}
......@@ -7400,6 +7447,8 @@ static int io_sq_thread(void *data)
set_cpus_allowed_ptr(current, cpu_online_mask);
current->flags |= PF_NO_SETAFFINITY;
audit_alloc_kernel(current);
mutex_lock(&sqd->lock);
while (1) {
bool cap_entries, sqt_spin = false;
......@@ -7465,6 +7514,8 @@ static int io_sq_thread(void *data)
io_run_task_work();
mutex_unlock(&sqd->lock);
audit_free(current);
complete(&sqd->exited);
do_exit(0);
}
......@@ -8622,6 +8673,10 @@ static __cold int io_sq_offload_create(struct io_ring_ctx *ctx,
struct io_sq_data *sqd;
bool attached;
ret = security_uring_sqpoll();
if (ret)
return ret;
sqd = io_get_sq_data(p, &attached);
if (IS_ERR(sqd)) {
ret = PTR_ERR(sqd);
......@@ -10276,8 +10331,8 @@ static struct file *io_uring_get_file(struct io_ring_ctx *ctx)
return ERR_PTR(ret);
#endif
file = anon_inode_getfile("[io_uring]", &io_uring_fops, ctx,
O_RDWR | O_CLOEXEC);
file = anon_inode_getfile_secure("[io_uring]", &io_uring_fops, ctx,
O_RDWR | O_CLOEXEC, NULL);
#if defined(CONFIG_UNIX)
if (IS_ERR(file)) {
sock_release(ctx->ring_sock);
......
......@@ -127,7 +127,8 @@ nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
return NULL;
err = security_dentry_init_security(dentry, sattr->ia_mode,
&dentry->d_name, (void **)&label->label, &label->len);
&dentry->d_name, NULL,
(void **)&label->label, &label->len);
if (err == 0)
return label;
......
......@@ -15,6 +15,10 @@ struct inode;
struct file *anon_inode_getfile(const char *name,
const struct file_operations *fops,
void *priv, int flags);
struct file *anon_inode_getfile_secure(const char *name,
const struct file_operations *fops,
void *priv, int flags,
const struct inode *context_inode);
int anon_inode_getfd(const char *name, const struct file_operations *fops,
void *priv, int flags);
int anon_inode_getfd_secure(const char *name,
......
......@@ -286,7 +286,10 @@ static inline int audit_signal_info(int sig, struct task_struct *t)
/* These are defined in auditsc.c */
/* Public API */
extern int audit_alloc(struct task_struct *task);
extern int audit_alloc_kernel(struct task_struct *task);
extern void __audit_free(struct task_struct *task);
extern void __audit_uring_entry(u8 op);
extern void __audit_uring_exit(int success, long code);
extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1,
unsigned long a2, unsigned long a3);
extern void __audit_syscall_exit(int ret_success, long ret_value);
......@@ -323,6 +326,21 @@ static inline void audit_free(struct task_struct *task)
if (unlikely(task->audit_context))
__audit_free(task);
}
static inline void audit_uring_entry(u8 op)
{
/*
* We intentionally check audit_context() before audit_enabled as most
* Linux systems (as of ~2021) rely on systemd which forces audit to
* be enabled regardless of the user's audit configuration.
*/
if (unlikely(audit_context() && audit_enabled))
__audit_uring_entry(op);
}
static inline void audit_uring_exit(int success, long code)
{
if (unlikely(!audit_dummy_context()))
__audit_uring_exit(success, code);
}
static inline void audit_syscall_entry(int major, unsigned long a0,
unsigned long a1, unsigned long a2,
unsigned long a3)
......@@ -554,8 +572,16 @@ static inline int audit_alloc(struct task_struct *task)
{
return 0;
}
static inline int audit_alloc_kernel(struct task_struct *task)
{
return 0;
}
static inline void audit_free(struct task_struct *task)
{ }
static inline void audit_uring_entry(u8 op)
{ }
static inline void audit_uring_exit(int success, long code)
{ }
static inline void audit_syscall_entry(int major, unsigned long a0,
unsigned long a1, unsigned long a2,
unsigned long a3)
......
......@@ -26,13 +26,13 @@
* #undef LSM_HOOK
* };
*/
LSM_HOOK(int, 0, binder_set_context_mgr, struct task_struct *mgr)
LSM_HOOK(int, 0, binder_transaction, struct task_struct *from,
struct task_struct *to)
LSM_HOOK(int, 0, binder_transfer_binder, struct task_struct *from,
struct task_struct *to)
LSM_HOOK(int, 0, binder_transfer_file, struct task_struct *from,
struct task_struct *to, struct file *file)
LSM_HOOK(int, 0, binder_set_context_mgr, const struct cred *mgr)
LSM_HOOK(int, 0, binder_transaction, const struct cred *from,
const struct cred *to)
LSM_HOOK(int, 0, binder_transfer_binder, const struct cred *from,
const struct cred *to)
LSM_HOOK(int, 0, binder_transfer_file, const struct cred *from,
const struct cred *to, struct file *file)
LSM_HOOK(int, 0, ptrace_access_check, struct task_struct *child,
unsigned int mode)
LSM_HOOK(int, 0, ptrace_traceme, struct task_struct *parent)
......@@ -83,7 +83,8 @@ LSM_HOOK(int, 0, sb_add_mnt_opt, const char *option, const char *val,
LSM_HOOK(int, 0, move_mount, const struct path *from_path,
const struct path *to_path)
LSM_HOOK(int, 0, dentry_init_security, struct dentry *dentry,
int mode, const struct qstr *name, void **ctx, u32 *ctxlen)
int mode, const struct qstr *name, const char **xattr_name,
void **ctx, u32 *ctxlen)
LSM_HOOK(int, 0, dentry_create_files_as, struct dentry *dentry, int mode,
struct qstr *name, const struct cred *old, struct cred *new)
......@@ -402,3 +403,8 @@ LSM_HOOK(void, LSM_RET_VOID, perf_event_free, struct perf_event *event)
LSM_HOOK(int, 0, perf_event_read, struct perf_event *event)
LSM_HOOK(int, 0, perf_event_write, struct perf_event *event)
#endif /* CONFIG_PERF_EVENTS */
#ifdef CONFIG_IO_URING
LSM_HOOK(int, 0, uring_override_creds, const struct cred *new)
LSM_HOOK(int, 0, uring_sqpoll, void)
#endif /* CONFIG_IO_URING */
......@@ -196,6 +196,9 @@
* @dentry dentry to use in calculating the context.
* @mode mode used to determine resource type.
* @name name of the last path component used to create file
* @xattr_name pointer to place the pointer to security xattr name.
* Caller does not have to free the resulting pointer. Its
* a pointer to static string.
* @ctx pointer to place the pointer to the resulting context in.
* @ctxlen point to place the length of the resulting context.
* @dentry_create_files_as:
......@@ -1313,22 +1316,22 @@
*
* @binder_set_context_mgr:
* Check whether @mgr is allowed to be the binder context manager.
* @mgr contains the task_struct for the task being registered.
* @mgr contains the struct cred for the current binder process.
* Return 0 if permission is granted.
* @binder_transaction:
* Check whether @from is allowed to invoke a binder transaction call
* to @to.
* @from contains the task_struct for the sending task.
* @to contains the task_struct for the receiving task.
* @from contains the struct cred for the sending process.
* @to contains the struct cred for the receiving process.
* @binder_transfer_binder:
* Check whether @from is allowed to transfer a binder reference to @to.
* @from contains the task_struct for the sending task.
* @to contains the task_struct for the receiving task.
* @from contains the struct cred for the sending process.
* @to contains the struct cred for the receiving process.
* @binder_transfer_file:
* Check whether @from is allowed to transfer @file to @to.
* @from contains the task_struct for the sending task.
* @from contains the struct cred for the sending process.
* @file contains the struct file being transferred.
* @to contains the task_struct for the receiving task.
* @to contains the struct cred for the receiving process.
*
* @ptrace_access_check:
* Check permission before allowing the current process to trace the
......@@ -1557,6 +1560,19 @@
* Read perf_event security info if allowed.
* @perf_event_write:
* Write perf_event security info if allowed.
*
* Security hooks for io_uring
*
* @uring_override_creds:
* Check if the current task, executing an io_uring operation, is allowed
* to override it's credentials with @new.
*
* @new: the new creds to use
*
* @uring_sqpoll:
* Check whether the current task is allowed to spawn a io_uring polling
* thread (IORING_SETUP_SQPOLL).
*
*/
union security_list_options {
#define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__);
......
......@@ -258,13 +258,13 @@ extern int security_init(void);
extern int early_security_init(void);
/* Security operations */
int security_binder_set_context_mgr(struct task_struct *mgr);
int security_binder_transaction(struct task_struct *from,
struct task_struct *to);
int security_binder_transfer_binder(struct task_struct *from,
struct task_struct *to);
int security_binder_transfer_file(struct task_struct *from,
struct task_struct *to, struct file *file);
int security_binder_set_context_mgr(const struct cred *mgr);
int security_binder_transaction(const struct cred *from,
const struct cred *to);
int security_binder_transfer_binder(const struct cred *from,
const struct cred *to);
int security_binder_transfer_file(const struct cred *from,
const struct cred *to, struct file *file);
int security_ptrace_access_check(struct task_struct *child, unsigned int mode);
int security_ptrace_traceme(struct task_struct *parent);
int security_capget(struct task_struct *target,
......@@ -317,8 +317,9 @@ int security_add_mnt_opt(const char *option, const char *val,
int len, void **mnt_opts);
int security_move_mount(const struct path *from_path, const struct path *to_path);
int security_dentry_init_security(struct dentry *dentry, int mode,
const struct qstr *name, void **ctx,
u32 *ctxlen);
const struct qstr *name,
const char **xattr_name, void **ctx,
u32 *ctxlen);
int security_dentry_create_files_as(struct dentry *dentry, int mode,
struct qstr *name,
const struct cred *old,
......@@ -508,25 +509,25 @@ static inline int early_security_init(void)
return 0;
}
static inline int security_binder_set_context_mgr(struct task_struct *mgr)
static inline int security_binder_set_context_mgr(const struct cred *mgr)
{
return 0;
}
static inline int security_binder_transaction(struct task_struct *from,
struct task_struct *to)
static inline int security_binder_transaction(const struct cred *from,
const struct cred *to)
{
return 0;
}
static inline int security_binder_transfer_binder(struct task_struct *from,
struct task_struct *to)
static inline int security_binder_transfer_binder(const struct cred *from,
const struct cred *to)
{
return 0;
}
static inline int security_binder_transfer_file(struct task_struct *from,
struct task_struct *to,
static inline int security_binder_transfer_file(const struct cred *from,
const struct cred *to,
struct file *file)
{
return 0;
......@@ -739,6 +740,7 @@ static inline void security_inode_free(struct inode *inode)
static inline int security_dentry_init_security(struct dentry *dentry,
int mode,
const struct qstr *name,
const char **xattr_name,
void **ctx,
u32 *ctxlen)
{
......@@ -1041,6 +1043,11 @@ static inline void security_transfer_creds(struct cred *new,
{
}
static inline void security_cred_getsecid(const struct cred *c, u32 *secid)
{
*secid = 0;
}
static inline int security_kernel_act_as(struct cred *cred, u32 secid)
{
return 0;
......@@ -2038,4 +2045,20 @@ static inline int security_perf_event_write(struct perf_event *event)
#endif /* CONFIG_SECURITY */
#endif /* CONFIG_PERF_EVENTS */
#ifdef CONFIG_IO_URING
#ifdef CONFIG_SECURITY
extern int security_uring_override_creds(const struct cred *new);
extern int security_uring_sqpoll(void);
#else
static inline int security_uring_override_creds(const struct cred *new)
{
return 0;
}
static inline int security_uring_sqpoll(void)
{
return 0;
}
#endif /* CONFIG_SECURITY */
#endif /* CONFIG_IO_URING */
#endif /* ! __LINUX_SECURITY_H */
......@@ -118,6 +118,7 @@
#define AUDIT_TIME_ADJNTPVAL 1333 /* NTP value adjustment */
#define AUDIT_BPF 1334 /* BPF subsystem */
#define AUDIT_EVENT_LISTENER 1335 /* Task joined multicast read socket */
#define AUDIT_URINGOP 1336 /* io_uring operation */
#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
......@@ -166,8 +167,9 @@
#define AUDIT_FILTER_EXCLUDE 0x05 /* Apply rule before record creation */
#define AUDIT_FILTER_TYPE AUDIT_FILTER_EXCLUDE /* obsolete misleading naming */
#define AUDIT_FILTER_FS 0x06 /* Apply rule at __audit_inode_child */
#define AUDIT_FILTER_URING_EXIT 0x07 /* Apply rule at io_uring op exit */
#define AUDIT_NR_FILTERS 7
#define AUDIT_NR_FILTERS 8
#define AUDIT_FILTER_PREPEND 0x10 /* Prepend to front of list */
......
......@@ -100,10 +100,15 @@ struct audit_proctitle {
/* The per-task audit context. */
struct audit_context {
int dummy; /* must be the first element */
int in_syscall; /* 1 if task is in a syscall */
enum {
AUDIT_CTX_UNUSED, /* audit_context is currently unused */
AUDIT_CTX_SYSCALL, /* in use by syscall */
AUDIT_CTX_URING, /* in use by io_uring */
} context;
enum audit_state state, current_state;
unsigned int serial; /* serial number for record */
int major; /* syscall number */
int uring_op; /* uring operation */
struct timespec64 ctime; /* time of syscall entry */
unsigned long argv[4]; /* syscall arguments */
long return_code;/* syscall return code */
......
......@@ -726,7 +726,8 @@ int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op)
{
if (pathname[0] != '/' ||
rule->listnr != AUDIT_FILTER_EXIT ||
(rule->listnr != AUDIT_FILTER_EXIT &&
rule->listnr != AUDIT_FILTER_URING_EXIT) ||
op != Audit_equal ||
rule->inode_f || rule->watch || rule->tree)
return -EINVAL;
......
......@@ -183,7 +183,8 @@ int audit_to_watch(struct audit_krule *krule, char *path, int len, u32 op)
return -EOPNOTSUPP;
if (path[0] != '/' || path[len-1] == '/' ||
krule->listnr != AUDIT_FILTER_EXIT ||
(krule->listnr != AUDIT_FILTER_EXIT &&
krule->listnr != AUDIT_FILTER_URING_EXIT) ||
op != Audit_equal ||
krule->inode_f || krule->watch || krule->tree)
return -EINVAL;
......
......@@ -44,7 +44,8 @@ struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
LIST_HEAD_INIT(audit_filter_list[4]),
LIST_HEAD_INIT(audit_filter_list[5]),
LIST_HEAD_INIT(audit_filter_list[6]),
#if AUDIT_NR_FILTERS != 7
LIST_HEAD_INIT(audit_filter_list[7]),
#if AUDIT_NR_FILTERS != 8
#error Fix audit_filter_list initialiser
#endif
};
......@@ -56,6 +57,7 @@ static struct list_head audit_rules_list[AUDIT_NR_FILTERS] = {
LIST_HEAD_INIT(audit_rules_list[4]),
LIST_HEAD_INIT(audit_rules_list[5]),
LIST_HEAD_INIT(audit_rules_list[6]),
LIST_HEAD_INIT(audit_rules_list[7]),
};
DEFINE_MUTEX(audit_filter_mutex);
......@@ -151,7 +153,8 @@ char *audit_unpack_string(void **bufp, size_t *remain, size_t len)
static inline int audit_to_inode(struct audit_krule *krule,
struct audit_field *f)
{
if (krule->listnr != AUDIT_FILTER_EXIT ||
if ((krule->listnr != AUDIT_FILTER_EXIT &&
krule->listnr != AUDIT_FILTER_URING_EXIT) ||
krule->inode_f || krule->watch || krule->tree ||
(f->op != Audit_equal && f->op != Audit_not_equal))
return -EINVAL;
......@@ -248,6 +251,7 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule_data *
pr_err("AUDIT_FILTER_ENTRY is deprecated\n");
goto exit_err;
case AUDIT_FILTER_EXIT:
case AUDIT_FILTER_URING_EXIT:
case AUDIT_FILTER_TASK:
#endif
case AUDIT_FILTER_USER:
......@@ -332,6 +336,10 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f)
if (entry->rule.listnr != AUDIT_FILTER_FS)
return -EINVAL;
break;
case AUDIT_PERM:
if (entry->rule.listnr == AUDIT_FILTER_URING_EXIT)
return -EINVAL;
break;
}
switch (entry->rule.listnr) {
......@@ -980,7 +988,8 @@ static inline int audit_add_rule(struct audit_entry *entry)
}
entry->rule.prio = ~0ULL;
if (entry->rule.listnr == AUDIT_FILTER_EXIT) {
if (entry->rule.listnr == AUDIT_FILTER_EXIT ||
entry->rule.listnr == AUDIT_FILTER_URING_EXIT) {
if (entry->rule.flags & AUDIT_FILTER_PREPEND)
entry->rule.prio = ++prio_high;
else
......
This diff is collapsed.
......@@ -706,7 +706,7 @@ static int lsm_superblock_alloc(struct super_block *sb)
#define LSM_RET_DEFAULT(NAME) (NAME##_default)
#define DECLARE_LSM_RET_DEFAULT_void(DEFAULT, NAME)
#define DECLARE_LSM_RET_DEFAULT_int(DEFAULT, NAME) \
static const int LSM_RET_DEFAULT(NAME) = (DEFAULT);
static const int __maybe_unused LSM_RET_DEFAULT(NAME) = (DEFAULT);
#define LSM_HOOK(RET, DEFAULT, NAME, ...) \
DECLARE_LSM_RET_DEFAULT_##RET(DEFAULT, NAME)
......@@ -747,25 +747,25 @@ static int lsm_superblock_alloc(struct super_block *sb)
/* Security operations */
int security_binder_set_context_mgr(struct task_struct *mgr)
int security_binder_set_context_mgr(const struct cred *mgr)
{
return call_int_hook(binder_set_context_mgr, 0, mgr);
}
int security_binder_transaction(struct task_struct *from,
struct task_struct *to)
int security_binder_transaction(const struct cred *from,
const struct cred *to)
{
return call_int_hook(binder_transaction, 0, from, to);
}
int security_binder_transfer_binder(struct task_struct *from,
struct task_struct *to)
int security_binder_transfer_binder(const struct cred *from,
const struct cred *to)
{
return call_int_hook(binder_transfer_binder, 0, from, to);
}
int security_binder_transfer_file(struct task_struct *from,
struct task_struct *to, struct file *file)
int security_binder_transfer_file(const struct cred *from,
const struct cred *to, struct file *file)
{
return call_int_hook(binder_transfer_file, 0, from, to, file);
}
......@@ -1052,11 +1052,12 @@ void security_inode_free(struct inode *inode)
}
int security_dentry_init_security(struct dentry *dentry, int mode,
const struct qstr *name, void **ctx,
u32 *ctxlen)
const struct qstr *name,
const char **xattr_name, void **ctx,
u32 *ctxlen)
{
return call_int_hook(dentry_init_security, -EOPNOTSUPP, dentry, mode,
name, ctx, ctxlen);
name, xattr_name, ctx, ctxlen);
}
EXPORT_SYMBOL(security_dentry_init_security);
......@@ -2625,3 +2626,15 @@ int security_perf_event_write(struct perf_event *event)
return call_int_hook(perf_event_write, 0, event);
}
#endif /* CONFIG_PERF_EVENTS */
#ifdef CONFIG_IO_URING
int security_uring_override_creds(const struct cred *new)
{
return call_int_hook(uring_override_creds, 0, new);
}
int security_uring_sqpoll(void)
{
return call_int_hook(uring_sqpoll, 0);
}
#endif /* CONFIG_IO_URING */
......@@ -547,6 +547,7 @@ static inline struct avc_node *avc_search_node(struct selinux_avc *avc,
/**
* avc_lookup - Look up an AVC entry.
* @avc: the access vector cache
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
......@@ -597,6 +598,7 @@ static int avc_latest_notif_update(struct selinux_avc *avc,
/**
* avc_insert - Insert an AVC entry.
* @avc: the access vector cache
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
......@@ -825,9 +827,14 @@ int __init avc_add_callback(int (*callback)(u32 event), u32 events)
/**
* avc_update_node - Update an AVC entry
* @avc: the access vector cache
* @event : Updating event
* @perms : Permission mask bits
* @ssid,@tsid,@tclass : identifier of an AVC entry
* @driver: xperm driver information
* @xperm: xperm permissions
* @ssid: AVC entry source sid
* @tsid: AVC entry target sid
* @tclass : AVC entry target object class
* @seqno : sequence number when decision was made
* @xpd: extended_perms_decision to be added to the node
* @flags: the AVC_* flags, e.g. AVC_EXTENDED_PERMS, or 0.
......@@ -928,6 +935,7 @@ static int avc_update_node(struct selinux_avc *avc,
/**
* avc_flush - Flush the cache
* @avc: the access vector cache
*/
static void avc_flush(struct selinux_avc *avc)
{
......@@ -956,6 +964,7 @@ static void avc_flush(struct selinux_avc *avc)
/**
* avc_ss_reset - Flush the cache and revalidate migrated permissions.
* @avc: the access vector cache
* @seqno: policy sequence number
*/
int avc_ss_reset(struct selinux_avc *avc, u32 seqno)
......@@ -1105,6 +1114,7 @@ int avc_has_extended_perms(struct selinux_state *state,
/**
* avc_has_perm_noaudit - Check permissions but perform no auditing.
* @state: SELinux state
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
......@@ -1156,6 +1166,7 @@ inline int avc_has_perm_noaudit(struct selinux_state *state,
/**
* avc_has_perm - Check permissions and perform any appropriate auditing.
* @state: SELinux state
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
......
This diff is collapsed.
......@@ -250,10 +250,10 @@ struct security_class_mapping secclass_map[] = {
{ COMMON_SOCK_PERMS, NULL } },
{ "perf_event",
{ "open", "cpu", "kernel", "tracepoint", "read", "write", NULL } },
{ "lockdown",
{ "integrity", "confidentiality", NULL } },
{ "anon_inode",
{ COMMON_FILE_PERMS, NULL } },
{ "io_uring",
{ "override_creds", "sqpoll", NULL } },
{ NULL }
};
......
......@@ -29,6 +29,7 @@
/**
* selinux_netlbl_sidlookup_cached - Cache a SID lookup
* @skb: the packet
* @family: the packet's address family
* @secattr: the NetLabel security attributes
* @sid: the SID
*
......@@ -128,6 +129,7 @@ void selinux_netlbl_cache_invalidate(void)
/**
* selinux_netlbl_err - Handle a NetLabel packet error
* @skb: the packet
* @family: the packet's address family
* @error: the error code
* @gateway: true if host is acting as a gateway, false otherwise
*
......@@ -160,7 +162,6 @@ void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec)
/**
* selinux_netlbl_sk_security_reset - Reset the NetLabel fields
* @sksec: the sk_security_struct
* @family: the socket family
*
* Description:
* Called when the NetLabel state of a sk_security_struct needs to be reset.
......@@ -313,6 +314,7 @@ int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep,
/**
* selinux_netlbl_inet_conn_request - Label an incoming stream connection
* @req: incoming connection request socket
* @family: the request socket's address family
*
* Description:
* A new incoming connection request is represented by @req, we need to label
......@@ -343,6 +345,7 @@ int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
/**
* selinux_netlbl_inet_csk_clone - Initialize the newly created sock
* @sk: the new sock
* @family: the sock's address family
*
* Description:
* A new connection has been established using @sk, we've already labeled the
......@@ -378,7 +381,7 @@ void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk)
/**
* selinux_netlbl_socket_post_create - Label a socket using NetLabel
* @sock: the socket to label
* @sk: the sock to label
* @family: protocol family
*
* Description:
......
......@@ -73,7 +73,7 @@ static unsigned int sel_netport_hashfn(u16 pnum)
/**
* sel_netport_find - Search for a port record
* @protocol: protocol
* @port: pnum
* @pnum: port
*
* Description:
* Search the network port table and return the matching record. If an entry
......
......@@ -8,6 +8,7 @@
#include <linux/slab.h>
#include <linux/errno.h>
#include "hashtab.h"
#include "security.h"
static struct kmem_cache *hashtab_node_cachep __ro_after_init;
......
......@@ -553,6 +553,7 @@ int mls_compute_sid(struct policydb *p,
#ifdef CONFIG_NETLABEL
/**
* mls_export_netlbl_lvl - Export the MLS sensitivity levels to NetLabel
* @p: the policy
* @context: the security context
* @secattr: the NetLabel security attributes
*
......@@ -574,6 +575,7 @@ void mls_export_netlbl_lvl(struct policydb *p,
/**
* mls_import_netlbl_lvl - Import the NetLabel MLS sensitivity levels
* @p: the policy
* @context: the security context
* @secattr: the NetLabel security attributes
*
......@@ -595,6 +597,7 @@ void mls_import_netlbl_lvl(struct policydb *p,
/**
* mls_export_netlbl_cat - Export the MLS categories to NetLabel
* @p: the policy
* @context: the security context
* @secattr: the NetLabel security attributes
*
......@@ -622,6 +625,7 @@ int mls_export_netlbl_cat(struct policydb *p,
/**
* mls_import_netlbl_cat - Import the MLS categories from NetLabel
* @p: the policy
* @context: the security context
* @secattr: the NetLabel security attributes
*
......
......@@ -1102,7 +1102,7 @@ void security_compute_xperms_decision(struct selinux_state *state,
* @state: SELinux state
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
* @orig_tclass: target security class
* @avd: access vector decisions
* @xperms: extended permissions
*
......@@ -1626,6 +1626,7 @@ int security_context_str_to_sid(struct selinux_state *state,
* @scontext_len: length in bytes
* @sid: security identifier, SID
* @def_sid: default SID to assign on error
* @gfp_flags: the allocator get-free-page (GFP) flags
*
* Obtains a SID associated with the security context that
* has the string representation specified by @scontext.
......@@ -1919,6 +1920,7 @@ static int security_compute_sid(struct selinux_state *state,
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
* @qstr: object name
* @out_sid: security identifier for new subject/object
*
* Compute a SID to use for labeling a new subject or object in the
......@@ -1947,6 +1949,7 @@ int security_transition_sid_user(struct selinux_state *state,
/**
* security_member_sid - Compute the SID for member selection.
* @state: SELinux state
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
......@@ -2273,6 +2276,7 @@ void selinux_policy_commit(struct selinux_state *state,
* @state: SELinux state
* @data: binary policy data
* @len: length of data in bytes
* @load_state: policy load state
*
* Load a new set of security policy configuration data,
* validate it and convert the SID table as necessary.
......@@ -2376,6 +2380,43 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len,
return rc;
}
/**
* ocontext_to_sid - Helper to safely get sid for an ocontext
* @sidtab: SID table
* @c: ocontext structure
* @index: index of the context entry (0 or 1)
* @out_sid: pointer to the resulting SID value
*
* For all ocontexts except OCON_ISID the SID fields are populated
* on-demand when needed. Since updating the SID value is an SMP-sensitive
* operation, this helper must be used to do that safely.
*
* WARNING: This function may return -ESTALE, indicating that the caller
* must retry the operation after re-acquiring the policy pointer!
*/
static int ocontext_to_sid(struct sidtab *sidtab, struct ocontext *c,
size_t index, u32 *out_sid)
{
int rc;
u32 sid;
/* Ensure the associated sidtab entry is visible to this thread. */
sid = smp_load_acquire(&c->sid[index]);
if (!sid) {
rc = sidtab_context_to_sid(sidtab, &c->context[index], &sid);
if (rc)
return rc;
/*
* Ensure the new sidtab entry is visible to other threads
* when they see the SID.
*/
smp_store_release(&c->sid[index], sid);
}
*out_sid = sid;
return 0;
}
/**
* security_port_sid - Obtain the SID for a port.
* @state: SELinux state
......@@ -2414,17 +2455,13 @@ int security_port_sid(struct selinux_state *state,
}
if (c) {
if (!c->sid[0]) {
rc = sidtab_context_to_sid(sidtab, &c->context[0],
&c->sid[0]);
if (rc == -ESTALE) {
rcu_read_unlock();
goto retry;
}
if (rc)
goto out;
rc = ocontext_to_sid(sidtab, c, 0, out_sid);
if (rc == -ESTALE) {
rcu_read_unlock();
goto retry;
}
*out_sid = c->sid[0];
if (rc)
goto out;
} else {
*out_sid = SECINITSID_PORT;
}
......@@ -2473,18 +2510,13 @@ int security_ib_pkey_sid(struct selinux_state *state,
}
if (c) {
if (!c->sid[0]) {
rc = sidtab_context_to_sid(sidtab,
&c->context[0],
&c->sid[0]);
if (rc == -ESTALE) {
rcu_read_unlock();
goto retry;
}
if (rc)
goto out;
rc = ocontext_to_sid(sidtab, c, 0, out_sid);
if (rc == -ESTALE) {
rcu_read_unlock();
goto retry;
}
*out_sid = c->sid[0];
if (rc)
goto out;
} else
*out_sid = SECINITSID_UNLABELED;
......@@ -2497,7 +2529,7 @@ int security_ib_pkey_sid(struct selinux_state *state,
* security_ib_endport_sid - Obtain the SID for a subnet management interface.
* @state: SELinux state
* @dev_name: device name
* @port: port number
* @port_num: port number
* @out_sid: security identifier
*/
int security_ib_endport_sid(struct selinux_state *state,
......@@ -2533,17 +2565,13 @@ int security_ib_endport_sid(struct selinux_state *state,
}
if (c) {
if (!c->sid[0]) {
rc = sidtab_context_to_sid(sidtab, &c->context[0],
&c->sid[0]);
if (rc == -ESTALE) {
rcu_read_unlock();
goto retry;
}
if (rc)
goto out;
rc = ocontext_to_sid(sidtab, c, 0, out_sid);
if (rc == -ESTALE) {
rcu_read_unlock();
goto retry;
}
*out_sid = c->sid[0];
if (rc)
goto out;
} else
*out_sid = SECINITSID_UNLABELED;
......@@ -2587,25 +2615,13 @@ int security_netif_sid(struct selinux_state *state,
}
if (c) {
if (!c->sid[0] || !c->sid[1]) {
rc = sidtab_context_to_sid(sidtab, &c->context[0],
&c->sid[0]);
if (rc == -ESTALE) {
rcu_read_unlock();
goto retry;
}
if (rc)
goto out;
rc = sidtab_context_to_sid(sidtab, &c->context[1],
&c->sid[1]);
if (rc == -ESTALE) {
rcu_read_unlock();
goto retry;
}
if (rc)
goto out;
rc = ocontext_to_sid(sidtab, c, 0, if_sid);
if (rc == -ESTALE) {
rcu_read_unlock();
goto retry;
}
*if_sid = c->sid[0];
if (rc)
goto out;
} else
*if_sid = SECINITSID_NETIF;
......@@ -2697,18 +2713,13 @@ int security_node_sid(struct selinux_state *state,
}
if (c) {
if (!c->sid[0]) {
rc = sidtab_context_to_sid(sidtab,
&c->context[0],
&c->sid[0]);
if (rc == -ESTALE) {
rcu_read_unlock();
goto retry;
}
if (rc)
goto out;
rc = ocontext_to_sid(sidtab, c, 0, out_sid);
if (rc == -ESTALE) {
rcu_read_unlock();
goto retry;
}
*out_sid = c->sid[0];
if (rc)
goto out;
} else {
*out_sid = SECINITSID_NODE;
}
......@@ -2849,9 +2860,10 @@ int security_get_user_sids(struct selinux_state *state,
/**
* __security_genfs_sid - Helper to obtain a SID for a file in a filesystem
* @policy: policy
* @fstype: filesystem type
* @path: path from root of mount
* @sclass: file security class
* @orig_sclass: file security class
* @sid: SID for path
*
* Obtain a SID to use for a file in a filesystem that
......@@ -2873,7 +2885,7 @@ static inline int __security_genfs_sid(struct selinux_policy *policy,
u16 sclass;
struct genfs *genfs;
struct ocontext *c;
int rc, cmp = 0;
int cmp = 0;
while (path[0] == '/' && path[1] == '/')
path++;
......@@ -2887,9 +2899,8 @@ static inline int __security_genfs_sid(struct selinux_policy *policy,
break;
}
rc = -ENOENT;
if (!genfs || cmp)
goto out;
return -ENOENT;
for (c = genfs->head; c; c = c->next) {
len = strlen(c->u.name);
......@@ -2898,20 +2909,10 @@ static inline int __security_genfs_sid(struct selinux_policy *policy,
break;
}
rc = -ENOENT;
if (!c)
goto out;
if (!c->sid[0]) {
rc = sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]);
if (rc)
goto out;
}
return -ENOENT;
*sid = c->sid[0];
rc = 0;
out:
return rc;
return ocontext_to_sid(sidtab, c, 0, sid);
}
/**
......@@ -2919,7 +2920,7 @@ static inline int __security_genfs_sid(struct selinux_policy *policy,
* @state: SELinux state
* @fstype: filesystem type
* @path: path from root of mount
* @sclass: file security class
* @orig_sclass: file security class
* @sid: SID for path
*
* Acquire policy_rwlock before calling __security_genfs_sid() and release
......@@ -2996,17 +2997,13 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb)
if (c) {
sbsec->behavior = c->v.behavior;
if (!c->sid[0]) {
rc = sidtab_context_to_sid(sidtab, &c->context[0],
&c->sid[0]);
if (rc == -ESTALE) {
rcu_read_unlock();
goto retry;
}
if (rc)
goto out;
rc = ocontext_to_sid(sidtab, c, 0, &sbsec->sid);
if (rc == -ESTALE) {
rcu_read_unlock();
goto retry;
}
sbsec->sid = c->sid[0];
if (rc)
goto out;
} else {
rc = __security_genfs_sid(policy, fstype, "/",
SECCLASS_DIR, &sbsec->sid);
......@@ -3305,6 +3302,7 @@ int security_sid_mls_copy(struct selinux_state *state,
* @nlbl_sid: NetLabel SID
* @nlbl_type: NetLabel labeling protocol type
* @xfrm_sid: XFRM SID
* @peer_sid: network peer sid
*
* Description:
* Compare the @nlbl_sid and @xfrm_sid values and if the two SIDs can be
......
......@@ -4700,6 +4700,48 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
return 0;
}
#ifdef CONFIG_IO_URING
/**
* smack_uring_override_creds - Is io_uring cred override allowed?
* @new: the target creds
*
* Check to see if the current task is allowed to override it's credentials
* to service an io_uring operation.
*/
static int smack_uring_override_creds(const struct cred *new)
{
struct task_smack *tsp = smack_cred(current_cred());
struct task_smack *nsp = smack_cred(new);
/*
* Allow the degenerate case where the new Smack value is
* the same as the current Smack value.
*/
if (tsp->smk_task == nsp->smk_task)
return 0;
if (smack_privileged_cred(CAP_MAC_OVERRIDE, current_cred()))
return 0;
return -EPERM;
}
/**
* smack_uring_sqpoll - check if a io_uring polling thread can be created
*
* Check to see if the current task is allowed to create a new io_uring
* kernel polling thread.
*/
static int smack_uring_sqpoll(void)
{
if (smack_privileged_cred(CAP_MAC_ADMIN, current_cred()))
return 0;
return -EPERM;
}
#endif /* CONFIG_IO_URING */
struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
.lbs_cred = sizeof(struct task_smack),
.lbs_file = sizeof(struct smack_known *),
......@@ -4852,6 +4894,10 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(inode_copy_up, smack_inode_copy_up),
LSM_HOOK_INIT(inode_copy_up_xattr, smack_inode_copy_up_xattr),
LSM_HOOK_INIT(dentry_create_files_as, smack_dentry_create_files_as),
#ifdef CONFIG_IO_URING
LSM_HOOK_INIT(uring_override_creds, smack_uring_override_creds),
LSM_HOOK_INIT(uring_sqpoll, smack_uring_sqpoll),
#endif
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment