Skip to content

Commit

Permalink
security: report the module name to security_module_request
Browse files Browse the repository at this point in the history
For SELinux to do better filtering in userspace we send the name of the
module along with the AVC denial when a program is denied module_request.

Example output:

type=SYSCALL msg=audit(11/03/2009 10:59:43.510:9) : arch=x86_64 syscall=write success=yes exit=2 a0=3 a1=7fc28c0d56c0 a2=2 a3=7fffca0d7440 items=0 ppid=1727 pid=1729 auid=unset uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=unset comm=rpc.nfsd exe=/usr/sbin/rpc.nfsd subj=system_u:system_r:nfsd_t:s0 key=(null)
type=AVC msg=audit(11/03/2009 10:59:43.510:9) : avc:  denied  { module_request } for  pid=1729 comm=rpc.nfsd kmod="net-pf-10" scontext=system_u:system_r:nfsd_t:s0 tcontext=system_u:system_r:kernel_t:s0 tclass=system

Signed-off-by: Eric Paris <[email protected]>
Signed-off-by: James Morris <[email protected]>
  • Loading branch information
eparis authored and James Morris committed Nov 9, 2009
1 parent 6e65f92 commit dd8dbf2
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 20 deletions.
18 changes: 10 additions & 8 deletions include/linux/lsm_audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@

/* Auxiliary data to use in generating the audit record. */
struct common_audit_data {
char type;
#define LSM_AUDIT_DATA_FS 1
#define LSM_AUDIT_DATA_NET 2
#define LSM_AUDIT_DATA_CAP 3
#define LSM_AUDIT_DATA_IPC 4
#define LSM_AUDIT_DATA_TASK 5
#define LSM_AUDIT_DATA_KEY 6
#define LSM_AUDIT_NO_AUDIT 7
char type;
#define LSM_AUDIT_DATA_FS 1
#define LSM_AUDIT_DATA_NET 2
#define LSM_AUDIT_DATA_CAP 3
#define LSM_AUDIT_DATA_IPC 4
#define LSM_AUDIT_DATA_TASK 5
#define LSM_AUDIT_DATA_KEY 6
#define LSM_AUDIT_NO_AUDIT 7
#define LSM_AUDIT_DATA_KMOD 8
struct task_struct *tsk;
union {
struct {
Expand Down Expand Up @@ -66,6 +67,7 @@ struct common_audit_data {
char *key_desc;
} key_struct;
#endif
char *kmod_name;
} u;
/* this union contains LSM specific data */
union {
Expand Down
7 changes: 4 additions & 3 deletions include/linux/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* @kernel_module_request:
* Ability to trigger the kernel to automatically upcall to userspace for
* userspace to load a kernel module with the given name.
* @kmod_name name of the module requested by the kernel
* Return 0 if successful.
* @task_setuid:
* Check permission before setting one or more of the user identity
Expand Down Expand Up @@ -1577,7 +1578,7 @@ struct security_operations {
void (*cred_transfer)(struct cred *new, const struct cred *old);
int (*kernel_act_as)(struct cred *new, u32 secid);
int (*kernel_create_files_as)(struct cred *new, struct inode *inode);
int (*kernel_module_request)(void);
int (*kernel_module_request)(char *kmod_name);
int (*task_setuid) (uid_t id0, uid_t id1, uid_t id2, int flags);
int (*task_fix_setuid) (struct cred *new, const struct cred *old,
int flags);
Expand Down Expand Up @@ -1842,7 +1843,7 @@ void security_commit_creds(struct cred *new, const struct cred *old);
void security_transfer_creds(struct cred *new, const struct cred *old);
int security_kernel_act_as(struct cred *new, u32 secid);
int security_kernel_create_files_as(struct cred *new, struct inode *inode);
int security_kernel_module_request(void);
int security_kernel_module_request(char *kmod_name);
int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags);
int security_task_fix_setuid(struct cred *new, const struct cred *old,
int flags);
Expand Down Expand Up @@ -2407,7 +2408,7 @@ static inline int security_kernel_create_files_as(struct cred *cred,
return 0;
}

static inline int security_kernel_module_request(void)
static inline int security_kernel_module_request(char *kmod_name)
{
return 0;
}
Expand Down
8 changes: 4 additions & 4 deletions kernel/kmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,16 @@ int __request_module(bool wait, const char *fmt, ...)
#define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */
static int kmod_loop_msg;

ret = security_kernel_module_request();
if (ret)
return ret;

va_start(args, fmt);
ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
va_end(args);
if (ret >= MODULE_NAME_LEN)
return -ENAMETOOLONG;

ret = security_kernel_module_request(module_name);
if (ret)
return ret;

/* If modprobe needs a service that is in a module, we get a recursive
* loop. Limit the number of running kmod threads to max_threads/2 or
* MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method
Expand Down
2 changes: 1 addition & 1 deletion security/capability.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ static int cap_kernel_create_files_as(struct cred *new, struct inode *inode)
return 0;
}

static int cap_kernel_module_request(void)
static int cap_kernel_module_request(char *kmod_name)
{
return 0;
}
Expand Down
4 changes: 4 additions & 0 deletions security/lsm_audit.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,10 @@ static void dump_common_audit_data(struct audit_buffer *ab,
}
break;
#endif
case LSM_AUDIT_DATA_KMOD:
audit_log_format(ab, " kmod=");
audit_log_untrustedstring(ab, a->u.kmod_name);
break;
} /* switch (a->type) */
}

Expand Down
4 changes: 2 additions & 2 deletions security/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -764,9 +764,9 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode)
return security_ops->kernel_create_files_as(new, inode);
}

int security_kernel_module_request(void)
int security_kernel_module_request(char *kmod_name)
{
return security_ops->kernel_module_request();
return security_ops->kernel_module_request(kmod_name);
}

int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
Expand Down
13 changes: 11 additions & 2 deletions security/selinux/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -3337,9 +3337,18 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
return 0;
}

static int selinux_kernel_module_request(void)
static int selinux_kernel_module_request(char *kmod_name)
{
return task_has_system(current, SYSTEM__MODULE_REQUEST);
u32 sid;
struct common_audit_data ad;

sid = task_sid(current);

COMMON_AUDIT_DATA_INIT(&ad, KMOD);
ad.u.kmod_name = kmod_name;

return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
SYSTEM__MODULE_REQUEST, &ad);
}

static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
Expand Down

0 comments on commit dd8dbf2

Please sign in to comment.