Skip to content

Commit e4e55b4

Browse files
Tetsuo HandaJames Morris
authored andcommitted
LSM: Revive security_task_alloc() hook and per "struct task_struct" security blob.
We switched from "struct task_struct"->security to "struct cred"->security in Linux 2.6.29. But not all LSM modules were happy with that change. TOMOYO LSM module is an example which want to use per "struct task_struct" security blob, for TOMOYO's security context is defined based on "struct task_struct" rather than "struct cred". AppArmor LSM module is another example which want to use it, for AppArmor is currently abusing the cred a little bit to store the change_hat and setexeccon info. Although security_task_free() hook was revived in Linux 3.4 because Yama LSM module wanted to release per "struct task_struct" security blob, security_task_alloc() hook and "struct task_struct"->security field were not revived. Nowadays, we are getting proposals of lightweight LSM modules which want to use per "struct task_struct" security blob. We are already allowing multiple concurrent LSM modules (up to one fully armored module which uses "struct cred"->security field or exclusive hooks like security_xfrm_state_pol_flow_match(), plus unlimited number of lightweight modules which do not use "struct cred"->security nor exclusive hooks) as long as they are built into the kernel. But this patch does not implement variable length "struct task_struct"->security field which will become needed when multiple LSM modules want to use "struct task_struct"-> security field. Although it won't be difficult to implement variable length "struct task_struct"->security field, let's think about it after we merged this patch. Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Acked-by: John Johansen <john.johansen@canonical.com> Acked-by: Serge Hallyn <serge@hallyn.com> Acked-by: Casey Schaufler <casey@schaufler-ca.com> Tested-by: Djalal Harouni <tixxdz@gmail.com> Acked-by: José Bollo <jobol@nonadev.net> Cc: Paul Moore <paul@paul-moore.com> Cc: Stephen Smalley <sds@tycho.nsa.gov> Cc: Eric Paris <eparis@parisplace.org> Cc: Kees Cook <keescook@chromium.org> Cc: James Morris <james.l.morris@oracle.com> Cc: José Bollo <jobol@nonadev.net> Signed-off-by: James Morris <james.l.morris@oracle.com>
1 parent 840c91d commit e4e55b4

File tree

6 files changed

+37
-2
lines changed

6 files changed

+37
-2
lines changed

include/linux/init_task.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,12 @@ extern struct cred init_cred;
210210
# define INIT_TASK_TI(tsk)
211211
#endif
212212

213+
#ifdef CONFIG_SECURITY
214+
#define INIT_TASK_SECURITY .security = NULL,
215+
#else
216+
#define INIT_TASK_SECURITY
217+
#endif
218+
213219
/*
214220
* INIT_TASK is used to set up the first task table, touch at
215221
* your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -288,6 +294,7 @@ extern struct cred init_cred;
288294
INIT_VTIME(tsk) \
289295
INIT_NUMA_BALANCING(tsk) \
290296
INIT_KASAN(tsk) \
297+
INIT_TASK_SECURITY \
291298
}
292299

293300

include/linux/lsm_hooks.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,8 +533,13 @@
533533
* manual page for definitions of the @clone_flags.
534534
* @clone_flags contains the flags indicating what should be shared.
535535
* Return 0 if permission is granted.
536+
* @task_alloc:
537+
* @task task being allocated.
538+
* @clone_flags contains the flags indicating what should be shared.
539+
* Handle allocation of task-related resources.
540+
* Returns a zero on success, negative values on failure.
536541
* @task_free:
537-
* @task task being freed
542+
* @task task about to be freed.
538543
* Handle release of task-related resources. (Note that this can be called
539544
* from interrupt context.)
540545
* @cred_alloc_blank:
@@ -1482,6 +1487,7 @@ union security_list_options {
14821487
int (*file_open)(struct file *file, const struct cred *cred);
14831488

14841489
int (*task_create)(unsigned long clone_flags);
1490+
int (*task_alloc)(struct task_struct *task, unsigned long clone_flags);
14851491
void (*task_free)(struct task_struct *task);
14861492
int (*cred_alloc_blank)(struct cred *cred, gfp_t gfp);
14871493
void (*cred_free)(struct cred *cred);
@@ -1748,6 +1754,7 @@ struct security_hook_heads {
17481754
struct list_head file_receive;
17491755
struct list_head file_open;
17501756
struct list_head task_create;
1757+
struct list_head task_alloc;
17511758
struct list_head task_free;
17521759
struct list_head cred_alloc_blank;
17531760
struct list_head cred_free;

include/linux/sched.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,10 @@ struct task_struct {
10371037
#ifdef CONFIG_THREAD_INFO_IN_TASK
10381038
/* A live task holds one reference: */
10391039
atomic_t stack_refcount;
1040+
#endif
1041+
#ifdef CONFIG_SECURITY
1042+
/* Used by LSM modules for access restriction: */
1043+
void *security;
10401044
#endif
10411045
/* CPU-specific state of this task: */
10421046
struct thread_struct thread;

include/linux/security.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ int security_file_send_sigiotask(struct task_struct *tsk,
308308
int security_file_receive(struct file *file);
309309
int security_file_open(struct file *file, const struct cred *cred);
310310
int security_task_create(unsigned long clone_flags);
311+
int security_task_alloc(struct task_struct *task, unsigned long clone_flags);
311312
void security_task_free(struct task_struct *task);
312313
int security_cred_alloc_blank(struct cred *cred, gfp_t gfp);
313314
void security_cred_free(struct cred *cred);
@@ -861,6 +862,12 @@ static inline int security_task_create(unsigned long clone_flags)
861862
return 0;
862863
}
863864

865+
static inline int security_task_alloc(struct task_struct *task,
866+
unsigned long clone_flags)
867+
{
868+
return 0;
869+
}
870+
864871
static inline void security_task_free(struct task_struct *task)
865872
{ }
866873

kernel/fork.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1679,9 +1679,12 @@ static __latent_entropy struct task_struct *copy_process(
16791679
goto bad_fork_cleanup_perf;
16801680
/* copy all the process information */
16811681
shm_init_task(p);
1682-
retval = copy_semundo(clone_flags, p);
1682+
retval = security_task_alloc(p, clone_flags);
16831683
if (retval)
16841684
goto bad_fork_cleanup_audit;
1685+
retval = copy_semundo(clone_flags, p);
1686+
if (retval)
1687+
goto bad_fork_cleanup_security;
16851688
retval = copy_files(clone_flags, p);
16861689
if (retval)
16871690
goto bad_fork_cleanup_semundo;
@@ -1903,6 +1906,8 @@ static __latent_entropy struct task_struct *copy_process(
19031906
exit_files(p); /* blocking */
19041907
bad_fork_cleanup_semundo:
19051908
exit_sem(p);
1909+
bad_fork_cleanup_security:
1910+
security_task_free(p);
19061911
bad_fork_cleanup_audit:
19071912
audit_free(p);
19081913
bad_fork_cleanup_perf:

security/security.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,11 @@ int security_task_create(unsigned long clone_flags)
937937
return call_int_hook(task_create, 0, clone_flags);
938938
}
939939

940+
int security_task_alloc(struct task_struct *task, unsigned long clone_flags)
941+
{
942+
return call_int_hook(task_alloc, 0, task, clone_flags);
943+
}
944+
940945
void security_task_free(struct task_struct *task)
941946
{
942947
call_void_hook(task_free, task);

0 commit comments

Comments
 (0)