diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-07 14:44:01 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-07 14:44:01 -0500 |
| commit | ae5906ceee038ea29ff5162d1bcd18fb50af8b94 (patch) | |
| tree | 841a11c6d3c3afcf7e4d57be370ebcf57aab214a /security | |
| parent | 1fc1cd8399ab5541a488a7e47b2f21537dd76c2d (diff) | |
| parent | 468e91cecb3218afd684b8c422490dfebe0691bb (diff) | |
Merge branch 'next-general' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris:
- Extend LSM stacking to allow sharing of cred, file, ipc, inode, and
task blobs. This paves the way for more full-featured LSMs to be
merged, and is specifically aimed at LandLock and SARA LSMs. This
work is from Casey and Kees.
- There's a new LSM from Micah Morton: "SafeSetID gates the setid
family of syscalls to restrict UID/GID transitions from a given
UID/GID to only those approved by a system-wide whitelist." This
feature is currently shipping in ChromeOS.
* 'next-general' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (62 commits)
keys: fix missing __user in KEYCTL_PKEY_QUERY
LSM: Update list of SECURITYFS users in Kconfig
LSM: Ignore "security=" when "lsm=" is specified
LSM: Update function documentation for cap_capable
security: mark expected switch fall-throughs and add a missing break
tomoyo: Bump version.
LSM: fix return value check in safesetid_init_securityfs()
LSM: SafeSetID: add selftest
LSM: SafeSetID: remove unused include
LSM: SafeSetID: 'depend' on CONFIG_SECURITY
LSM: Add 'name' field for SafeSetID in DEFINE_LSM
LSM: add SafeSetID module that gates setid calls
LSM: add SafeSetID module that gates setid calls
tomoyo: Allow multiple use_group lines.
tomoyo: Coding style fix.
tomoyo: Swicth from cred->security to task_struct->security.
security: keys: annotate implicit fall throughs
security: keys: annotate implicit fall throughs
security: keys: annotate implicit fall through
capabilities:: annotate implicit fall through
...
Diffstat (limited to 'security')
58 files changed, 2018 insertions, 965 deletions
diff --git a/security/Kconfig b/security/Kconfig index e4fe2f3c2c65..1d6463fb1450 100644 --- a/security/Kconfig +++ b/security/Kconfig | |||
| @@ -40,8 +40,7 @@ config SECURITYFS | |||
| 40 | bool "Enable the securityfs filesystem" | 40 | bool "Enable the securityfs filesystem" |
| 41 | help | 41 | help |
| 42 | This will build the securityfs filesystem. It is currently used by | 42 | This will build the securityfs filesystem. It is currently used by |
| 43 | the TPM bios character driver and IMA, an integrity provider. It is | 43 | various security modules (AppArmor, IMA, SafeSetID, TOMOYO, TPM). |
| 44 | not used by SELinux or SMACK. | ||
| 45 | 44 | ||
| 46 | If you are unsure how to answer this question, answer N. | 45 | If you are unsure how to answer this question, answer N. |
| 47 | 46 | ||
| @@ -236,45 +235,19 @@ source "security/tomoyo/Kconfig" | |||
| 236 | source "security/apparmor/Kconfig" | 235 | source "security/apparmor/Kconfig" |
| 237 | source "security/loadpin/Kconfig" | 236 | source "security/loadpin/Kconfig" |
| 238 | source "security/yama/Kconfig" | 237 | source "security/yama/Kconfig" |
| 238 | source "security/safesetid/Kconfig" | ||
| 239 | 239 | ||
| 240 | source "security/integrity/Kconfig" | 240 | source "security/integrity/Kconfig" |
| 241 | 241 | ||
| 242 | choice | 242 | config LSM |
| 243 | prompt "Default security module" | 243 | string "Ordered list of enabled LSMs" |
| 244 | default DEFAULT_SECURITY_SELINUX if SECURITY_SELINUX | 244 | default "yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor" |
| 245 | default DEFAULT_SECURITY_SMACK if SECURITY_SMACK | ||
| 246 | default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO | ||
| 247 | default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR | ||
| 248 | default DEFAULT_SECURITY_DAC | ||
| 249 | |||
| 250 | help | 245 | help |
| 251 | Select the security module that will be used by default if the | 246 | A comma-separated list of LSMs, in initialization order. |
| 252 | kernel parameter security= is not specified. | 247 | Any LSMs left off this list will be ignored. This can be |
| 253 | 248 | controlled at boot with the "lsm=" parameter. | |
| 254 | config DEFAULT_SECURITY_SELINUX | ||
| 255 | bool "SELinux" if SECURITY_SELINUX=y | ||
| 256 | |||
| 257 | config DEFAULT_SECURITY_SMACK | ||
| 258 | bool "Simplified Mandatory Access Control" if SECURITY_SMACK=y | ||
| 259 | |||
| 260 | config DEFAULT_SECURITY_TOMOYO | ||
| 261 | bool "TOMOYO" if SECURITY_TOMOYO=y | ||
| 262 | |||
| 263 | config DEFAULT_SECURITY_APPARMOR | ||
| 264 | bool "AppArmor" if SECURITY_APPARMOR=y | ||
| 265 | |||
| 266 | config DEFAULT_SECURITY_DAC | ||
| 267 | bool "Unix Discretionary Access Controls" | ||
| 268 | |||
| 269 | endchoice | ||
| 270 | 249 | ||
| 271 | config DEFAULT_SECURITY | 250 | If unsure, leave this as the default. |
| 272 | string | ||
| 273 | default "selinux" if DEFAULT_SECURITY_SELINUX | ||
| 274 | default "smack" if DEFAULT_SECURITY_SMACK | ||
| 275 | default "tomoyo" if DEFAULT_SECURITY_TOMOYO | ||
| 276 | default "apparmor" if DEFAULT_SECURITY_APPARMOR | ||
| 277 | default "" if DEFAULT_SECURITY_DAC | ||
| 278 | 251 | ||
| 279 | endmenu | 252 | endmenu |
| 280 | 253 | ||
diff --git a/security/Makefile b/security/Makefile index 4d2d3782ddef..c598b904938f 100644 --- a/security/Makefile +++ b/security/Makefile | |||
| @@ -10,6 +10,7 @@ subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo | |||
| 10 | subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor | 10 | subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor |
| 11 | subdir-$(CONFIG_SECURITY_YAMA) += yama | 11 | subdir-$(CONFIG_SECURITY_YAMA) += yama |
| 12 | subdir-$(CONFIG_SECURITY_LOADPIN) += loadpin | 12 | subdir-$(CONFIG_SECURITY_LOADPIN) += loadpin |
| 13 | subdir-$(CONFIG_SECURITY_SAFESETID) += safesetid | ||
| 13 | 14 | ||
| 14 | # always enable default capabilities | 15 | # always enable default capabilities |
| 15 | obj-y += commoncap.o | 16 | obj-y += commoncap.o |
| @@ -25,6 +26,7 @@ obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/ | |||
| 25 | obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/ | 26 | obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/ |
| 26 | obj-$(CONFIG_SECURITY_YAMA) += yama/ | 27 | obj-$(CONFIG_SECURITY_YAMA) += yama/ |
| 27 | obj-$(CONFIG_SECURITY_LOADPIN) += loadpin/ | 28 | obj-$(CONFIG_SECURITY_LOADPIN) += loadpin/ |
| 29 | obj-$(CONFIG_SECURITY_SAFESETID) += safesetid/ | ||
| 28 | obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o | 30 | obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o |
| 29 | 31 | ||
| 30 | # Object integrity file lists | 32 | # Object integrity file lists |
diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig index b6b68a7750ce..3de21f46c82a 100644 --- a/security/apparmor/Kconfig +++ b/security/apparmor/Kconfig | |||
| @@ -14,22 +14,6 @@ config SECURITY_APPARMOR | |||
| 14 | 14 | ||
| 15 | If you are unsure how to answer this question, answer N. | 15 | If you are unsure how to answer this question, answer N. |
| 16 | 16 | ||
| 17 | config SECURITY_APPARMOR_BOOTPARAM_VALUE | ||
| 18 | int "AppArmor boot parameter default value" | ||
| 19 | depends on SECURITY_APPARMOR | ||
| 20 | range 0 1 | ||
| 21 | default 1 | ||
| 22 | help | ||
| 23 | This option sets the default value for the kernel parameter | ||
| 24 | 'apparmor', which allows AppArmor to be enabled or disabled | ||
| 25 | at boot. If this option is set to 0 (zero), the AppArmor | ||
| 26 | kernel parameter will default to 0, disabling AppArmor at | ||
| 27 | boot. If this option is set to 1 (one), the AppArmor | ||
| 28 | kernel parameter will default to 1, enabling AppArmor at | ||
| 29 | boot. | ||
| 30 | |||
| 31 | If you are unsure how to answer this question, answer 1. | ||
| 32 | |||
| 33 | config SECURITY_APPARMOR_HASH | 17 | config SECURITY_APPARMOR_HASH |
| 34 | bool "Enable introspection of sha1 hashes for loaded profiles" | 18 | bool "Enable introspection of sha1 hashes for loaded profiles" |
| 35 | depends on SECURITY_APPARMOR | 19 | depends on SECURITY_APPARMOR |
diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c index 253ef6e9d445..752f73980e30 100644 --- a/security/apparmor/capability.c +++ b/security/apparmor/capability.c | |||
| @@ -110,13 +110,13 @@ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile, | |||
| 110 | * profile_capable - test if profile allows use of capability @cap | 110 | * profile_capable - test if profile allows use of capability @cap |
| 111 | * @profile: profile being enforced (NOT NULL, NOT unconfined) | 111 | * @profile: profile being enforced (NOT NULL, NOT unconfined) |
| 112 | * @cap: capability to test if allowed | 112 | * @cap: capability to test if allowed |
| 113 | * @audit: whether an audit record should be generated | 113 | * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated |
| 114 | * @sa: audit data (MAY BE NULL indicating no auditing) | 114 | * @sa: audit data (MAY BE NULL indicating no auditing) |
| 115 | * | 115 | * |
| 116 | * Returns: 0 if allowed else -EPERM | 116 | * Returns: 0 if allowed else -EPERM |
| 117 | */ | 117 | */ |
| 118 | static int profile_capable(struct aa_profile *profile, int cap, int audit, | 118 | static int profile_capable(struct aa_profile *profile, int cap, |
| 119 | struct common_audit_data *sa) | 119 | unsigned int opts, struct common_audit_data *sa) |
| 120 | { | 120 | { |
| 121 | int error; | 121 | int error; |
| 122 | 122 | ||
| @@ -126,7 +126,7 @@ static int profile_capable(struct aa_profile *profile, int cap, int audit, | |||
| 126 | else | 126 | else |
| 127 | error = -EPERM; | 127 | error = -EPERM; |
| 128 | 128 | ||
| 129 | if (audit == SECURITY_CAP_NOAUDIT) { | 129 | if (opts & CAP_OPT_NOAUDIT) { |
| 130 | if (!COMPLAIN_MODE(profile)) | 130 | if (!COMPLAIN_MODE(profile)) |
| 131 | return error; | 131 | return error; |
| 132 | /* audit the cap request in complain mode but note that it | 132 | /* audit the cap request in complain mode but note that it |
| @@ -142,13 +142,13 @@ static int profile_capable(struct aa_profile *profile, int cap, int audit, | |||
| 142 | * aa_capable - test permission to use capability | 142 | * aa_capable - test permission to use capability |
| 143 | * @label: label being tested for capability (NOT NULL) | 143 | * @label: label being tested for capability (NOT NULL) |
| 144 | * @cap: capability to be tested | 144 | * @cap: capability to be tested |
| 145 | * @audit: whether an audit record should be generated | 145 | * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated |
| 146 | * | 146 | * |
| 147 | * Look up capability in profile capability set. | 147 | * Look up capability in profile capability set. |
| 148 | * | 148 | * |
| 149 | * Returns: 0 on success, or else an error code. | 149 | * Returns: 0 on success, or else an error code. |
| 150 | */ | 150 | */ |
| 151 | int aa_capable(struct aa_label *label, int cap, int audit) | 151 | int aa_capable(struct aa_label *label, int cap, unsigned int opts) |
| 152 | { | 152 | { |
| 153 | struct aa_profile *profile; | 153 | struct aa_profile *profile; |
| 154 | int error = 0; | 154 | int error = 0; |
| @@ -156,7 +156,7 @@ int aa_capable(struct aa_label *label, int cap, int audit) | |||
| 156 | 156 | ||
| 157 | sa.u.cap = cap; | 157 | sa.u.cap = cap; |
| 158 | error = fn_for_each_confined(label, profile, | 158 | error = fn_for_each_confined(label, profile, |
| 159 | profile_capable(profile, cap, audit, &sa)); | 159 | profile_capable(profile, cap, opts, &sa)); |
| 160 | 160 | ||
| 161 | return error; | 161 | return error; |
| 162 | } | 162 | } |
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c index 11975ec8d566..ca2dccf5b445 100644 --- a/security/apparmor/domain.c +++ b/security/apparmor/domain.c | |||
| @@ -572,7 +572,7 @@ static struct aa_label *x_to_label(struct aa_profile *profile, | |||
| 572 | stack = NULL; | 572 | stack = NULL; |
| 573 | break; | 573 | break; |
| 574 | } | 574 | } |
| 575 | /* fall through to X_NAME */ | 575 | /* fall through - to X_NAME */ |
| 576 | case AA_X_NAME: | 576 | case AA_X_NAME: |
| 577 | if (xindex & AA_X_CHILD) | 577 | if (xindex & AA_X_CHILD) |
| 578 | /* released by caller */ | 578 | /* released by caller */ |
| @@ -975,7 +975,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) | |||
| 975 | } | 975 | } |
| 976 | aa_put_label(cred_label(bprm->cred)); | 976 | aa_put_label(cred_label(bprm->cred)); |
| 977 | /* transfer reference, released when cred is freed */ | 977 | /* transfer reference, released when cred is freed */ |
| 978 | cred_label(bprm->cred) = new; | 978 | set_cred_label(bprm->cred, new); |
| 979 | 979 | ||
| 980 | done: | 980 | done: |
| 981 | aa_put_label(label); | 981 | aa_put_label(label); |
diff --git a/security/apparmor/include/capability.h b/security/apparmor/include/capability.h index e0304e2aeb7f..1b3663b6ab12 100644 --- a/security/apparmor/include/capability.h +++ b/security/apparmor/include/capability.h | |||
| @@ -40,7 +40,7 @@ struct aa_caps { | |||
| 40 | 40 | ||
| 41 | extern struct aa_sfs_entry aa_sfs_entry_caps[]; | 41 | extern struct aa_sfs_entry aa_sfs_entry_caps[]; |
| 42 | 42 | ||
| 43 | int aa_capable(struct aa_label *label, int cap, int audit); | 43 | int aa_capable(struct aa_label *label, int cap, unsigned int opts); |
| 44 | 44 | ||
| 45 | static inline void aa_free_cap_rules(struct aa_caps *caps) | 45 | static inline void aa_free_cap_rules(struct aa_caps *caps) |
| 46 | { | 46 | { |
diff --git a/security/apparmor/include/cred.h b/security/apparmor/include/cred.h index 265ae6641a06..b9504a05fddc 100644 --- a/security/apparmor/include/cred.h +++ b/security/apparmor/include/cred.h | |||
| @@ -23,8 +23,22 @@ | |||
| 23 | #include "policy_ns.h" | 23 | #include "policy_ns.h" |
| 24 | #include "task.h" | 24 | #include "task.h" |
| 25 | 25 | ||
| 26 | #define cred_label(X) ((X)->security) | 26 | static inline struct aa_label *cred_label(const struct cred *cred) |
| 27 | { | ||
| 28 | struct aa_label **blob = cred->security + apparmor_blob_sizes.lbs_cred; | ||
| 29 | |||
| 30 | AA_BUG(!blob); | ||
| 31 | return *blob; | ||
| 32 | } | ||
| 27 | 33 | ||
| 34 | static inline void set_cred_label(const struct cred *cred, | ||
| 35 | struct aa_label *label) | ||
| 36 | { | ||
| 37 | struct aa_label **blob = cred->security + apparmor_blob_sizes.lbs_cred; | ||
| 38 | |||
| 39 | AA_BUG(!blob); | ||
| 40 | *blob = label; | ||
| 41 | } | ||
| 28 | 42 | ||
| 29 | /** | 43 | /** |
| 30 | * aa_cred_raw_label - obtain cred's label | 44 | * aa_cred_raw_label - obtain cred's label |
diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h index 4c2c8ac8842f..8be09208cf7c 100644 --- a/security/apparmor/include/file.h +++ b/security/apparmor/include/file.h | |||
| @@ -32,7 +32,10 @@ struct path; | |||
| 32 | AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_LOCK | \ | 32 | AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_LOCK | \ |
| 33 | AA_EXEC_MMAP | AA_MAY_LINK) | 33 | AA_EXEC_MMAP | AA_MAY_LINK) |
| 34 | 34 | ||
| 35 | #define file_ctx(X) ((struct aa_file_ctx *)(X)->f_security) | 35 | static inline struct aa_file_ctx *file_ctx(struct file *file) |
| 36 | { | ||
| 37 | return file->f_security + apparmor_blob_sizes.lbs_file; | ||
| 38 | } | ||
| 36 | 39 | ||
| 37 | /* struct aa_file_ctx - the AppArmor context the file was opened in | 40 | /* struct aa_file_ctx - the AppArmor context the file was opened in |
| 38 | * @lock: lock to update the ctx | 41 | * @lock: lock to update the ctx |
diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h index 6505e1ad9e23..bbe9b384d71d 100644 --- a/security/apparmor/include/lib.h +++ b/security/apparmor/include/lib.h | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
| 19 | #include <linux/lsm_hooks.h> | ||
| 19 | 20 | ||
| 20 | #include "match.h" | 21 | #include "match.h" |
| 21 | 22 | ||
| @@ -55,6 +56,9 @@ const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name, | |||
| 55 | size_t *ns_len); | 56 | size_t *ns_len); |
| 56 | void aa_info_message(const char *str); | 57 | void aa_info_message(const char *str); |
| 57 | 58 | ||
| 59 | /* Security blob offsets */ | ||
| 60 | extern struct lsm_blob_sizes apparmor_blob_sizes; | ||
| 61 | |||
| 58 | /** | 62 | /** |
| 59 | * aa_strneq - compare null terminated @str to a non null terminated substring | 63 | * aa_strneq - compare null terminated @str to a non null terminated substring |
| 60 | * @str: a null terminated string | 64 | * @str: a null terminated string |
diff --git a/security/apparmor/include/task.h b/security/apparmor/include/task.h index 55edaa1d83f8..311e652324e3 100644 --- a/security/apparmor/include/task.h +++ b/security/apparmor/include/task.h | |||
| @@ -14,7 +14,10 @@ | |||
| 14 | #ifndef __AA_TASK_H | 14 | #ifndef __AA_TASK_H |
| 15 | #define __AA_TASK_H | 15 | #define __AA_TASK_H |
| 16 | 16 | ||
| 17 | #define task_ctx(X) ((X)->security) | 17 | static inline struct aa_task_ctx *task_ctx(struct task_struct *task) |
| 18 | { | ||
| 19 | return task->security + apparmor_blob_sizes.lbs_task; | ||
| 20 | } | ||
| 18 | 21 | ||
| 19 | /* | 22 | /* |
| 20 | * struct aa_task_ctx - information for current task label change | 23 | * struct aa_task_ctx - information for current task label change |
| @@ -37,17 +40,6 @@ int aa_restore_previous_label(u64 cookie); | |||
| 37 | struct aa_label *aa_get_task_label(struct task_struct *task); | 40 | struct aa_label *aa_get_task_label(struct task_struct *task); |
| 38 | 41 | ||
| 39 | /** | 42 | /** |
| 40 | * aa_alloc_task_ctx - allocate a new task_ctx | ||
| 41 | * @flags: gfp flags for allocation | ||
| 42 | * | ||
| 43 | * Returns: allocated buffer or NULL on failure | ||
| 44 | */ | ||
| 45 | static inline struct aa_task_ctx *aa_alloc_task_ctx(gfp_t flags) | ||
| 46 | { | ||
| 47 | return kzalloc(sizeof(struct aa_task_ctx), flags); | ||
| 48 | } | ||
| 49 | |||
| 50 | /** | ||
| 51 | * aa_free_task_ctx - free a task_ctx | 43 | * aa_free_task_ctx - free a task_ctx |
| 52 | * @ctx: task_ctx to free (MAYBE NULL) | 44 | * @ctx: task_ctx to free (MAYBE NULL) |
| 53 | */ | 45 | */ |
| @@ -57,8 +49,6 @@ static inline void aa_free_task_ctx(struct aa_task_ctx *ctx) | |||
| 57 | aa_put_label(ctx->nnp); | 49 | aa_put_label(ctx->nnp); |
| 58 | aa_put_label(ctx->previous); | 50 | aa_put_label(ctx->previous); |
| 59 | aa_put_label(ctx->onexec); | 51 | aa_put_label(ctx->onexec); |
| 60 | |||
| 61 | kzfree(ctx); | ||
| 62 | } | 52 | } |
| 63 | } | 53 | } |
| 64 | 54 | ||
diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c index 527ea1557120..aacd1e95cb59 100644 --- a/security/apparmor/ipc.c +++ b/security/apparmor/ipc.c | |||
| @@ -107,7 +107,8 @@ static int profile_tracer_perm(struct aa_profile *tracer, | |||
| 107 | aad(sa)->label = &tracer->label; | 107 | aad(sa)->label = &tracer->label; |
| 108 | aad(sa)->peer = tracee; | 108 | aad(sa)->peer = tracee; |
| 109 | aad(sa)->request = 0; | 109 | aad(sa)->request = 0; |
| 110 | aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, 1); | 110 | aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE, |
| 111 | CAP_OPT_NONE); | ||
| 111 | 112 | ||
| 112 | return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb); | 113 | return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb); |
| 113 | } | 114 | } |
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 8db1731d046a..49d664ddff44 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c | |||
| @@ -60,7 +60,7 @@ DEFINE_PER_CPU(struct aa_buffers, aa_buffers); | |||
| 60 | static void apparmor_cred_free(struct cred *cred) | 60 | static void apparmor_cred_free(struct cred *cred) |
| 61 | { | 61 | { |
| 62 | aa_put_label(cred_label(cred)); | 62 | aa_put_label(cred_label(cred)); |
| 63 | cred_label(cred) = NULL; | 63 | set_cred_label(cred, NULL); |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | /* | 66 | /* |
| @@ -68,7 +68,7 @@ static void apparmor_cred_free(struct cred *cred) | |||
| 68 | */ | 68 | */ |
| 69 | static int apparmor_cred_alloc_blank(struct cred *cred, gfp_t gfp) | 69 | static int apparmor_cred_alloc_blank(struct cred *cred, gfp_t gfp) |
| 70 | { | 70 | { |
| 71 | cred_label(cred) = NULL; | 71 | set_cred_label(cred, NULL); |
| 72 | return 0; | 72 | return 0; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| @@ -78,7 +78,7 @@ static int apparmor_cred_alloc_blank(struct cred *cred, gfp_t gfp) | |||
| 78 | static int apparmor_cred_prepare(struct cred *new, const struct cred *old, | 78 | static int apparmor_cred_prepare(struct cred *new, const struct cred *old, |
| 79 | gfp_t gfp) | 79 | gfp_t gfp) |
| 80 | { | 80 | { |
| 81 | cred_label(new) = aa_get_newest_label(cred_label(old)); | 81 | set_cred_label(new, aa_get_newest_label(cred_label(old))); |
| 82 | return 0; | 82 | return 0; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| @@ -87,26 +87,21 @@ static int apparmor_cred_prepare(struct cred *new, const struct cred *old, | |||
| 87 | */ | 87 | */ |
| 88 | static void apparmor_cred_transfer(struct cred *new, const struct cred *old) | 88 | static void apparmor_cred_transfer(struct cred *new, const struct cred *old) |
| 89 | { | 89 | { |
| 90 | cred_label(new) = aa_get_newest_label(cred_label(old)); | 90 | set_cred_label(new, aa_get_newest_label(cred_label(old))); |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | static void apparmor_task_free(struct task_struct *task) | 93 | static void apparmor_task_free(struct task_struct *task) |
| 94 | { | 94 | { |
| 95 | 95 | ||
| 96 | aa_free_task_ctx(task_ctx(task)); | 96 | aa_free_task_ctx(task_ctx(task)); |
| 97 | task_ctx(task) = NULL; | ||
| 98 | } | 97 | } |
| 99 | 98 | ||
| 100 | static int apparmor_task_alloc(struct task_struct *task, | 99 | static int apparmor_task_alloc(struct task_struct *task, |
| 101 | unsigned long clone_flags) | 100 | unsigned long clone_flags) |
| 102 | { | 101 | { |
| 103 | struct aa_task_ctx *new = aa_alloc_task_ctx(GFP_KERNEL); | 102 | struct aa_task_ctx *new = task_ctx(task); |
| 104 | |||
| 105 | if (!new) | ||
| 106 | return -ENOMEM; | ||
| 107 | 103 | ||
| 108 | aa_dup_task_ctx(new, task_ctx(current)); | 104 | aa_dup_task_ctx(new, task_ctx(current)); |
| 109 | task_ctx(task) = new; | ||
| 110 | 105 | ||
| 111 | return 0; | 106 | return 0; |
| 112 | } | 107 | } |
| @@ -177,14 +172,14 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, | |||
| 177 | } | 172 | } |
| 178 | 173 | ||
| 179 | static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, | 174 | static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, |
| 180 | int cap, int audit) | 175 | int cap, unsigned int opts) |
| 181 | { | 176 | { |
| 182 | struct aa_label *label; | 177 | struct aa_label *label; |
| 183 | int error = 0; | 178 | int error = 0; |
| 184 | 179 | ||
| 185 | label = aa_get_newest_cred_label(cred); | 180 | label = aa_get_newest_cred_label(cred); |
| 186 | if (!unconfined(label)) | 181 | if (!unconfined(label)) |
| 187 | error = aa_capable(label, cap, audit); | 182 | error = aa_capable(label, cap, opts); |
| 188 | aa_put_label(label); | 183 | aa_put_label(label); |
| 189 | 184 | ||
| 190 | return error; | 185 | return error; |
| @@ -434,21 +429,21 @@ static int apparmor_file_open(struct file *file) | |||
| 434 | 429 | ||
| 435 | static int apparmor_file_alloc_security(struct file *file) | 430 | static int apparmor_file_alloc_security(struct file *file) |
| 436 | { | 431 | { |
| 437 | int error = 0; | 432 | struct aa_file_ctx *ctx = file_ctx(file); |
| 438 | |||
| 439 | /* freed by apparmor_file_free_security */ | ||
| 440 | struct aa_label *label = begin_current_label_crit_section(); | 433 | struct aa_label *label = begin_current_label_crit_section(); |
| 441 | file->f_security = aa_alloc_file_ctx(label, GFP_KERNEL); | ||
| 442 | if (!file_ctx(file)) | ||
| 443 | error = -ENOMEM; | ||
| 444 | end_current_label_crit_section(label); | ||
| 445 | 434 | ||
| 446 | return error; | 435 | spin_lock_init(&ctx->lock); |
| 436 | rcu_assign_pointer(ctx->label, aa_get_label(label)); | ||
| 437 | end_current_label_crit_section(label); | ||
| 438 | return 0; | ||
| 447 | } | 439 | } |
| 448 | 440 | ||
| 449 | static void apparmor_file_free_security(struct file *file) | 441 | static void apparmor_file_free_security(struct file *file) |
| 450 | { | 442 | { |
| 451 | aa_free_file_ctx(file_ctx(file)); | 443 | struct aa_file_ctx *ctx = file_ctx(file); |
| 444 | |||
| 445 | if (ctx) | ||
| 446 | aa_put_label(rcu_access_pointer(ctx->label)); | ||
| 452 | } | 447 | } |
| 453 | 448 | ||
| 454 | static int common_file_perm(const char *op, struct file *file, u32 mask) | 449 | static int common_file_perm(const char *op, struct file *file, u32 mask) |
| @@ -1151,6 +1146,15 @@ static int apparmor_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
| 1151 | } | 1146 | } |
| 1152 | #endif | 1147 | #endif |
| 1153 | 1148 | ||
| 1149 | /* | ||
| 1150 | * The cred blob is a pointer to, not an instance of, an aa_task_ctx. | ||
| 1151 | */ | ||
| 1152 | struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = { | ||
| 1153 | .lbs_cred = sizeof(struct aa_task_ctx *), | ||
| 1154 | .lbs_file = sizeof(struct aa_file_ctx), | ||
| 1155 | .lbs_task = sizeof(struct aa_task_ctx), | ||
| 1156 | }; | ||
| 1157 | |||
| 1154 | static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { | 1158 | static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { |
| 1155 | LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), | 1159 | LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), |
| 1156 | LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), | 1160 | LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), |
| @@ -1333,8 +1337,8 @@ bool aa_g_paranoid_load = true; | |||
| 1333 | module_param_named(paranoid_load, aa_g_paranoid_load, aabool, S_IRUGO); | 1337 | module_param_named(paranoid_load, aa_g_paranoid_load, aabool, S_IRUGO); |
| 1334 | 1338 | ||
| 1335 | /* Boot time disable flag */ | 1339 | /* Boot time disable flag */ |
| 1336 | static bool apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE; | 1340 | static int apparmor_enabled __lsm_ro_after_init = 1; |
| 1337 | module_param_named(enabled, apparmor_enabled, bool, S_IRUGO); | 1341 | module_param_named(enabled, apparmor_enabled, int, 0444); |
| 1338 | 1342 | ||
| 1339 | static int __init apparmor_enabled_setup(char *str) | 1343 | static int __init apparmor_enabled_setup(char *str) |
| 1340 | { | 1344 | { |
| @@ -1479,14 +1483,8 @@ static int param_set_mode(const char *val, const struct kernel_param *kp) | |||
| 1479 | static int __init set_init_ctx(void) | 1483 | static int __init set_init_ctx(void) |
| 1480 | { | 1484 | { |
| 1481 | struct cred *cred = (struct cred *)current->real_cred; | 1485 | struct cred *cred = (struct cred *)current->real_cred; |
| 1482 | struct aa_task_ctx *ctx; | ||
| 1483 | |||
| 1484 | ctx = aa_alloc_task_ctx(GFP_KERNEL); | ||
| 1485 | if (!ctx) | ||
| 1486 | return -ENOMEM; | ||
| 1487 | 1486 | ||
| 1488 | cred_label(cred) = aa_get_label(ns_unconfined(root_ns)); | 1487 | set_cred_label(cred, aa_get_label(ns_unconfined(root_ns))); |
| 1489 | task_ctx(current) = ctx; | ||
| 1490 | 1488 | ||
| 1491 | return 0; | 1489 | return 0; |
| 1492 | } | 1490 | } |
| @@ -1665,12 +1663,6 @@ static int __init apparmor_init(void) | |||
| 1665 | { | 1663 | { |
| 1666 | int error; | 1664 | int error; |
| 1667 | 1665 | ||
| 1668 | if (!apparmor_enabled || !security_module_enable("apparmor")) { | ||
| 1669 | aa_info_message("AppArmor disabled by boot time parameter"); | ||
| 1670 | apparmor_enabled = false; | ||
| 1671 | return 0; | ||
| 1672 | } | ||
| 1673 | |||
| 1674 | aa_secids_init(); | 1666 | aa_secids_init(); |
| 1675 | 1667 | ||
| 1676 | error = aa_setup_dfa_engine(); | 1668 | error = aa_setup_dfa_engine(); |
| @@ -1731,5 +1723,8 @@ alloc_out: | |||
| 1731 | 1723 | ||
| 1732 | DEFINE_LSM(apparmor) = { | 1724 | DEFINE_LSM(apparmor) = { |
| 1733 | .name = "apparmor", | 1725 | .name = "apparmor", |
| 1726 | .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE, | ||
| 1727 | .enabled = &apparmor_enabled, | ||
| 1728 | .blobs = &apparmor_blob_sizes, | ||
| 1734 | .init = apparmor_init, | 1729 | .init = apparmor_init, |
| 1735 | }; | 1730 | }; |
diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c index 95fd26d09757..552ed09cb47e 100644 --- a/security/apparmor/resource.c +++ b/security/apparmor/resource.c | |||
| @@ -124,7 +124,7 @@ int aa_task_setrlimit(struct aa_label *label, struct task_struct *task, | |||
| 124 | */ | 124 | */ |
| 125 | 125 | ||
| 126 | if (label != peer && | 126 | if (label != peer && |
| 127 | aa_capable(label, CAP_SYS_RESOURCE, SECURITY_CAP_NOAUDIT) != 0) | 127 | aa_capable(label, CAP_SYS_RESOURCE, CAP_OPT_NOAUDIT) != 0) |
| 128 | error = fn_for_each(label, profile, | 128 | error = fn_for_each(label, profile, |
| 129 | audit_resource(profile, resource, | 129 | audit_resource(profile, resource, |
| 130 | new_rlim->rlim_max, peer, | 130 | new_rlim->rlim_max, peer, |
diff --git a/security/apparmor/task.c b/security/apparmor/task.c index c6b78a14da91..4551110f0496 100644 --- a/security/apparmor/task.c +++ b/security/apparmor/task.c | |||
| @@ -81,7 +81,7 @@ int aa_replace_current_label(struct aa_label *label) | |||
| 81 | */ | 81 | */ |
| 82 | aa_get_label(label); | 82 | aa_get_label(label); |
| 83 | aa_put_label(cred_label(new)); | 83 | aa_put_label(cred_label(new)); |
| 84 | cred_label(new) = label; | 84 | set_cred_label(new, label); |
| 85 | 85 | ||
| 86 | commit_creds(new); | 86 | commit_creds(new); |
| 87 | return 0; | 87 | return 0; |
| @@ -138,7 +138,7 @@ int aa_set_current_hat(struct aa_label *label, u64 token) | |||
| 138 | return -EACCES; | 138 | return -EACCES; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | cred_label(new) = aa_get_newest_label(label); | 141 | set_cred_label(new, aa_get_newest_label(label)); |
| 142 | /* clear exec on switching context */ | 142 | /* clear exec on switching context */ |
| 143 | aa_put_label(ctx->onexec); | 143 | aa_put_label(ctx->onexec); |
| 144 | ctx->onexec = NULL; | 144 | ctx->onexec = NULL; |
| @@ -172,7 +172,7 @@ int aa_restore_previous_label(u64 token) | |||
| 172 | return -ENOMEM; | 172 | return -ENOMEM; |
| 173 | 173 | ||
| 174 | aa_put_label(cred_label(new)); | 174 | aa_put_label(cred_label(new)); |
| 175 | cred_label(new) = aa_get_newest_label(ctx->previous); | 175 | set_cred_label(new, aa_get_newest_label(ctx->previous)); |
| 176 | AA_BUG(!cred_label(new)); | 176 | AA_BUG(!cred_label(new)); |
| 177 | /* clear exec && prev information when restoring to previous context */ | 177 | /* clear exec && prev information when restoring to previous context */ |
| 178 | aa_clear_task_ctx_trans(ctx); | 178 | aa_clear_task_ctx_trans(ctx); |
diff --git a/security/commoncap.c b/security/commoncap.c index 232db019f051..f1d117c3d8ae 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
| @@ -57,7 +57,7 @@ static void warn_setuid_and_fcaps_mixed(const char *fname) | |||
| 57 | * @cred: The credentials to use | 57 | * @cred: The credentials to use |
| 58 | * @ns: The user namespace in which we need the capability | 58 | * @ns: The user namespace in which we need the capability |
| 59 | * @cap: The capability to check for | 59 | * @cap: The capability to check for |
| 60 | * @audit: Whether to write an audit message or not | 60 | * @opts: Bitmask of options defined in include/linux/security.h |
| 61 | * | 61 | * |
| 62 | * Determine whether the nominated task has the specified capability amongst | 62 | * Determine whether the nominated task has the specified capability amongst |
| 63 | * its effective set, returning 0 if it does, -ve if it does not. | 63 | * its effective set, returning 0 if it does, -ve if it does not. |
| @@ -68,7 +68,7 @@ static void warn_setuid_and_fcaps_mixed(const char *fname) | |||
| 68 | * kernel's capable() and has_capability() returns 1 for this case. | 68 | * kernel's capable() and has_capability() returns 1 for this case. |
| 69 | */ | 69 | */ |
| 70 | int cap_capable(const struct cred *cred, struct user_namespace *targ_ns, | 70 | int cap_capable(const struct cred *cred, struct user_namespace *targ_ns, |
| 71 | int cap, int audit) | 71 | int cap, unsigned int opts) |
| 72 | { | 72 | { |
| 73 | struct user_namespace *ns = targ_ns; | 73 | struct user_namespace *ns = targ_ns; |
| 74 | 74 | ||
| @@ -222,12 +222,11 @@ int cap_capget(struct task_struct *target, kernel_cap_t *effective, | |||
| 222 | */ | 222 | */ |
| 223 | static inline int cap_inh_is_capped(void) | 223 | static inline int cap_inh_is_capped(void) |
| 224 | { | 224 | { |
| 225 | |||
| 226 | /* they are so limited unless the current task has the CAP_SETPCAP | 225 | /* they are so limited unless the current task has the CAP_SETPCAP |
| 227 | * capability | 226 | * capability |
| 228 | */ | 227 | */ |
| 229 | if (cap_capable(current_cred(), current_cred()->user_ns, | 228 | if (cap_capable(current_cred(), current_cred()->user_ns, |
| 230 | CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0) | 229 | CAP_SETPCAP, CAP_OPT_NONE) == 0) |
| 231 | return 0; | 230 | return 0; |
| 232 | return 1; | 231 | return 1; |
| 233 | } | 232 | } |
| @@ -1208,8 +1207,9 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
| 1208 | || ((old->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ | 1207 | || ((old->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ |
| 1209 | || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ | 1208 | || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ |
| 1210 | || (cap_capable(current_cred(), | 1209 | || (cap_capable(current_cred(), |
| 1211 | current_cred()->user_ns, CAP_SETPCAP, | 1210 | current_cred()->user_ns, |
| 1212 | SECURITY_CAP_AUDIT) != 0) /*[4]*/ | 1211 | CAP_SETPCAP, |
| 1212 | CAP_OPT_NONE) != 0) /*[4]*/ | ||
| 1213 | /* | 1213 | /* |
| 1214 | * [1] no changing of bits that are locked | 1214 | * [1] no changing of bits that are locked |
| 1215 | * [2] no unlocking of locks | 1215 | * [2] no unlocking of locks |
| @@ -1304,9 +1304,10 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages) | |||
| 1304 | { | 1304 | { |
| 1305 | int cap_sys_admin = 0; | 1305 | int cap_sys_admin = 0; |
| 1306 | 1306 | ||
| 1307 | if (cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN, | 1307 | if (cap_capable(current_cred(), &init_user_ns, |
| 1308 | SECURITY_CAP_NOAUDIT) == 0) | 1308 | CAP_SYS_ADMIN, CAP_OPT_NOAUDIT) == 0) |
| 1309 | cap_sys_admin = 1; | 1309 | cap_sys_admin = 1; |
| 1310 | |||
| 1310 | return cap_sys_admin; | 1311 | return cap_sys_admin; |
| 1311 | } | 1312 | } |
| 1312 | 1313 | ||
| @@ -1325,7 +1326,7 @@ int cap_mmap_addr(unsigned long addr) | |||
| 1325 | 1326 | ||
| 1326 | if (addr < dac_mmap_min_addr) { | 1327 | if (addr < dac_mmap_min_addr) { |
| 1327 | ret = cap_capable(current_cred(), &init_user_ns, CAP_SYS_RAWIO, | 1328 | ret = cap_capable(current_cred(), &init_user_ns, CAP_SYS_RAWIO, |
| 1328 | SECURITY_CAP_AUDIT); | 1329 | CAP_OPT_NONE); |
| 1329 | /* set PF_SUPERPRIV if it turns out we allow the low mmap */ | 1330 | /* set PF_SUPERPRIV if it turns out we allow the low mmap */ |
| 1330 | if (ret == 0) | 1331 | if (ret == 0) |
| 1331 | current->flags |= PF_SUPERPRIV; | 1332 | current->flags |= PF_SUPERPRIV; |
| @@ -1362,10 +1363,17 @@ struct security_hook_list capability_hooks[] __lsm_ro_after_init = { | |||
| 1362 | LSM_HOOK_INIT(vm_enough_memory, cap_vm_enough_memory), | 1363 | LSM_HOOK_INIT(vm_enough_memory, cap_vm_enough_memory), |
| 1363 | }; | 1364 | }; |
| 1364 | 1365 | ||
| 1365 | void __init capability_add_hooks(void) | 1366 | static int __init capability_init(void) |
| 1366 | { | 1367 | { |
| 1367 | security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks), | 1368 | security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks), |
| 1368 | "capability"); | 1369 | "capability"); |
| 1370 | return 0; | ||
| 1369 | } | 1371 | } |
| 1370 | 1372 | ||
| 1373 | DEFINE_LSM(capability) = { | ||
| 1374 | .name = "capability", | ||
| 1375 | .order = LSM_ORDER_FIRST, | ||
| 1376 | .init = capability_init, | ||
| 1377 | }; | ||
| 1378 | |||
| 1371 | #endif /* CONFIG_SECURITY */ | 1379 | #endif /* CONFIG_SECURITY */ |
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index a2baa85ea2f5..5fb7127bbe68 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c | |||
| @@ -114,6 +114,7 @@ static void ima_set_cache_status(struct integrity_iint_cache *iint, | |||
| 114 | break; | 114 | break; |
| 115 | case CREDS_CHECK: | 115 | case CREDS_CHECK: |
| 116 | iint->ima_creds_status = status; | 116 | iint->ima_creds_status = status; |
| 117 | break; | ||
| 117 | case FILE_CHECK: | 118 | case FILE_CHECK: |
| 118 | case POST_SETATTR: | 119 | case POST_SETATTR: |
| 119 | iint->ima_file_status = status; | 120 | iint->ima_file_status = status; |
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 8bc8a1c8cb3f..122797023bdb 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c | |||
| @@ -938,10 +938,12 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) | |||
| 938 | case Opt_uid_gt: | 938 | case Opt_uid_gt: |
| 939 | case Opt_euid_gt: | 939 | case Opt_euid_gt: |
| 940 | entry->uid_op = &uid_gt; | 940 | entry->uid_op = &uid_gt; |
| 941 | /* fall through */ | ||
| 941 | case Opt_uid_lt: | 942 | case Opt_uid_lt: |
| 942 | case Opt_euid_lt: | 943 | case Opt_euid_lt: |
| 943 | if ((token == Opt_uid_lt) || (token == Opt_euid_lt)) | 944 | if ((token == Opt_uid_lt) || (token == Opt_euid_lt)) |
| 944 | entry->uid_op = &uid_lt; | 945 | entry->uid_op = &uid_lt; |
| 946 | /* fall through */ | ||
| 945 | case Opt_uid_eq: | 947 | case Opt_uid_eq: |
| 946 | case Opt_euid_eq: | 948 | case Opt_euid_eq: |
| 947 | uid_token = (token == Opt_uid_eq) || | 949 | uid_token = (token == Opt_uid_eq) || |
| @@ -970,9 +972,11 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) | |||
| 970 | break; | 972 | break; |
| 971 | case Opt_fowner_gt: | 973 | case Opt_fowner_gt: |
| 972 | entry->fowner_op = &uid_gt; | 974 | entry->fowner_op = &uid_gt; |
| 975 | /* fall through */ | ||
| 973 | case Opt_fowner_lt: | 976 | case Opt_fowner_lt: |
| 974 | if (token == Opt_fowner_lt) | 977 | if (token == Opt_fowner_lt) |
| 975 | entry->fowner_op = &uid_lt; | 978 | entry->fowner_op = &uid_lt; |
| 979 | /* fall through */ | ||
| 976 | case Opt_fowner_eq: | 980 | case Opt_fowner_eq: |
| 977 | ima_log_string_op(ab, "fowner", args[0].from, | 981 | ima_log_string_op(ab, "fowner", args[0].from, |
| 978 | entry->fowner_op); | 982 | entry->fowner_op); |
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c index 43752002c222..513b457ae900 100644 --- a/security/integrity/ima/ima_template_lib.c +++ b/security/integrity/ima/ima_template_lib.c | |||
| @@ -83,6 +83,7 @@ static void ima_show_template_data_ascii(struct seq_file *m, | |||
| 83 | /* skip ':' and '\0' */ | 83 | /* skip ':' and '\0' */ |
| 84 | buf_ptr += 2; | 84 | buf_ptr += 2; |
| 85 | buflen -= buf_ptr - field_data->data; | 85 | buflen -= buf_ptr - field_data->data; |
| 86 | /* fall through */ | ||
| 86 | case DATA_FMT_DIGEST: | 87 | case DATA_FMT_DIGEST: |
| 87 | case DATA_FMT_HEX: | 88 | case DATA_FMT_HEX: |
| 88 | if (!buflen) | 89 | if (!buflen) |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 7bbe03593e58..3e4053a217c3 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
| @@ -1752,7 +1752,7 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
| 1752 | return -EINVAL; | 1752 | return -EINVAL; |
| 1753 | return keyctl_pkey_query((key_serial_t)arg2, | 1753 | return keyctl_pkey_query((key_serial_t)arg2, |
| 1754 | (const char __user *)arg4, | 1754 | (const char __user *)arg4, |
| 1755 | (struct keyctl_pkey_query *)arg5); | 1755 | (struct keyctl_pkey_query __user *)arg5); |
| 1756 | 1756 | ||
| 1757 | case KEYCTL_PKEY_ENCRYPT: | 1757 | case KEYCTL_PKEY_ENCRYPT: |
| 1758 | case KEYCTL_PKEY_DECRYPT: | 1758 | case KEYCTL_PKEY_DECRYPT: |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index f81372f53dd7..e14f09e3a4b0 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
| @@ -246,6 +246,7 @@ static unsigned long keyring_get_key_chunk(const void *data, int level) | |||
| 246 | (ASSOC_ARRAY_KEY_CHUNK_SIZE - 8)); | 246 | (ASSOC_ARRAY_KEY_CHUNK_SIZE - 8)); |
| 247 | n--; | 247 | n--; |
| 248 | offset = 1; | 248 | offset = 1; |
| 249 | /* fall through */ | ||
| 249 | default: | 250 | default: |
| 250 | offset += sizeof(chunk) - 1; | 251 | offset += sizeof(chunk) - 1; |
| 251 | offset += (level - 3) * sizeof(chunk); | 252 | offset += (level - 3) * sizeof(chunk); |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 0e0b9ccad2f8..9320424c4a46 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
| @@ -380,6 +380,7 @@ key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx) | |||
| 380 | case -EAGAIN: /* no key */ | 380 | case -EAGAIN: /* no key */ |
| 381 | if (ret) | 381 | if (ret) |
| 382 | break; | 382 | break; |
| 383 | /* fall through */ | ||
| 383 | case -ENOKEY: /* negative key */ | 384 | case -ENOKEY: /* negative key */ |
| 384 | ret = key_ref; | 385 | ret = key_ref; |
| 385 | break; | 386 | break; |
| @@ -404,6 +405,7 @@ key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx) | |||
| 404 | case -EAGAIN: /* no key */ | 405 | case -EAGAIN: /* no key */ |
| 405 | if (ret) | 406 | if (ret) |
| 406 | break; | 407 | break; |
| 408 | /* fall through */ | ||
| 407 | case -ENOKEY: /* negative key */ | 409 | case -ENOKEY: /* negative key */ |
| 408 | ret = key_ref; | 410 | ret = key_ref; |
| 409 | break; | 411 | break; |
| @@ -424,6 +426,7 @@ key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx) | |||
| 424 | case -EAGAIN: /* no key */ | 426 | case -EAGAIN: /* no key */ |
| 425 | if (ret) | 427 | if (ret) |
| 426 | break; | 428 | break; |
| 429 | /* fall through */ | ||
| 427 | case -ENOKEY: /* negative key */ | 430 | case -ENOKEY: /* negative key */ |
| 428 | ret = key_ref; | 431 | ret = key_ref; |
| 429 | break; | 432 | break; |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 7a0c6b666ff0..2f17d84d46f1 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
| @@ -273,16 +273,19 @@ static int construct_get_dest_keyring(struct key **_dest_keyring) | |||
| 273 | } | 273 | } |
| 274 | } | 274 | } |
| 275 | 275 | ||
| 276 | /* fall through */ | ||
| 276 | case KEY_REQKEY_DEFL_THREAD_KEYRING: | 277 | case KEY_REQKEY_DEFL_THREAD_KEYRING: |
| 277 | dest_keyring = key_get(cred->thread_keyring); | 278 | dest_keyring = key_get(cred->thread_keyring); |
| 278 | if (dest_keyring) | 279 | if (dest_keyring) |
| 279 | break; | 280 | break; |
| 280 | 281 | ||
| 282 | /* fall through */ | ||
| 281 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: | 283 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: |
| 282 | dest_keyring = key_get(cred->process_keyring); | 284 | dest_keyring = key_get(cred->process_keyring); |
| 283 | if (dest_keyring) | 285 | if (dest_keyring) |
| 284 | break; | 286 | break; |
| 285 | 287 | ||
| 288 | /* fall through */ | ||
| 286 | case KEY_REQKEY_DEFL_SESSION_KEYRING: | 289 | case KEY_REQKEY_DEFL_SESSION_KEYRING: |
| 287 | rcu_read_lock(); | 290 | rcu_read_lock(); |
| 288 | dest_keyring = key_get( | 291 | dest_keyring = key_get( |
| @@ -292,6 +295,7 @@ static int construct_get_dest_keyring(struct key **_dest_keyring) | |||
| 292 | if (dest_keyring) | 295 | if (dest_keyring) |
| 293 | break; | 296 | break; |
| 294 | 297 | ||
| 298 | /* fall through */ | ||
| 295 | case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: | 299 | case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: |
| 296 | dest_keyring = | 300 | dest_keyring = |
| 297 | key_get(cred->user->session_keyring); | 301 | key_get(cred->user->session_keyring); |
diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c index 48f39631b370..055fb0a64169 100644 --- a/security/loadpin/loadpin.c +++ b/security/loadpin/loadpin.c | |||
| @@ -187,13 +187,19 @@ static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = { | |||
| 187 | LSM_HOOK_INIT(kernel_load_data, loadpin_load_data), | 187 | LSM_HOOK_INIT(kernel_load_data, loadpin_load_data), |
| 188 | }; | 188 | }; |
| 189 | 189 | ||
| 190 | void __init loadpin_add_hooks(void) | 190 | static int __init loadpin_init(void) |
| 191 | { | 191 | { |
| 192 | pr_info("ready to pin (currently %senforcing)\n", | 192 | pr_info("ready to pin (currently %senforcing)\n", |
| 193 | enforce ? "" : "not "); | 193 | enforce ? "" : "not "); |
| 194 | security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin"); | 194 | security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin"); |
| 195 | return 0; | ||
| 195 | } | 196 | } |
| 196 | 197 | ||
| 198 | DEFINE_LSM(loadpin) = { | ||
| 199 | .name = "loadpin", | ||
| 200 | .init = loadpin_init, | ||
| 201 | }; | ||
| 202 | |||
| 197 | /* Should not be mutable after boot, so not listed in sysfs (perm == 0). */ | 203 | /* Should not be mutable after boot, so not listed in sysfs (perm == 0). */ |
| 198 | module_param(enforce, int, 0); | 204 | module_param(enforce, int, 0); |
| 199 | MODULE_PARM_DESC(enforce, "Enforce module/firmware pinning"); | 205 | MODULE_PARM_DESC(enforce, "Enforce module/firmware pinning"); |
diff --git a/security/safesetid/Kconfig b/security/safesetid/Kconfig new file mode 100644 index 000000000000..4f415c4e3f93 --- /dev/null +++ b/security/safesetid/Kconfig | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | config SECURITY_SAFESETID | ||
| 2 | bool "Gate setid transitions to limit CAP_SET{U/G}ID capabilities" | ||
| 3 | depends on SECURITY | ||
| 4 | select SECURITYFS | ||
| 5 | default n | ||
| 6 | help | ||
| 7 | SafeSetID is an LSM module that gates the setid family of syscalls to | ||
| 8 | restrict UID/GID transitions from a given UID/GID to only those | ||
| 9 | approved by a system-wide whitelist. These restrictions also prohibit | ||
| 10 | the given UIDs/GIDs from obtaining auxiliary privileges associated | ||
| 11 | with CAP_SET{U/G}ID, such as allowing a user to set up user namespace | ||
| 12 | UID mappings. | ||
| 13 | |||
| 14 | If you are unsure how to answer this question, answer N. | ||
diff --git a/security/safesetid/Makefile b/security/safesetid/Makefile new file mode 100644 index 000000000000..6b0660321164 --- /dev/null +++ b/security/safesetid/Makefile | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | # | ||
| 3 | # Makefile for the safesetid LSM. | ||
| 4 | # | ||
| 5 | |||
| 6 | obj-$(CONFIG_SECURITY_SAFESETID) := safesetid.o | ||
| 7 | safesetid-y := lsm.o securityfs.o | ||
diff --git a/security/safesetid/lsm.c b/security/safesetid/lsm.c new file mode 100644 index 000000000000..cecd38e2ac80 --- /dev/null +++ b/security/safesetid/lsm.c | |||
| @@ -0,0 +1,277 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * SafeSetID Linux Security Module | ||
| 4 | * | ||
| 5 | * Author: Micah Morton <mortonm@chromium.org> | ||
| 6 | * | ||
| 7 | * Copyright (C) 2018 The Chromium OS Authors. | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2, as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #define pr_fmt(fmt) "SafeSetID: " fmt | ||
| 16 | |||
| 17 | #include <linux/hashtable.h> | ||
| 18 | #include <linux/lsm_hooks.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/ptrace.h> | ||
| 21 | #include <linux/sched/task_stack.h> | ||
| 22 | #include <linux/security.h> | ||
| 23 | |||
| 24 | /* Flag indicating whether initialization completed */ | ||
| 25 | int safesetid_initialized; | ||
| 26 | |||
| 27 | #define NUM_BITS 8 /* 128 buckets in hash table */ | ||
| 28 | |||
| 29 | static DEFINE_HASHTABLE(safesetid_whitelist_hashtable, NUM_BITS); | ||
| 30 | |||
| 31 | /* | ||
| 32 | * Hash table entry to store safesetid policy signifying that 'parent' user | ||
| 33 | * can setid to 'child' user. | ||
| 34 | */ | ||
| 35 | struct entry { | ||
| 36 | struct hlist_node next; | ||
| 37 | struct hlist_node dlist; /* for deletion cleanup */ | ||
| 38 | uint64_t parent_kuid; | ||
| 39 | uint64_t child_kuid; | ||
| 40 | }; | ||
| 41 | |||
| 42 | static DEFINE_SPINLOCK(safesetid_whitelist_hashtable_spinlock); | ||
| 43 | |||
| 44 | static bool check_setuid_policy_hashtable_key(kuid_t parent) | ||
| 45 | { | ||
| 46 | struct entry *entry; | ||
| 47 | |||
| 48 | rcu_read_lock(); | ||
| 49 | hash_for_each_possible_rcu(safesetid_whitelist_hashtable, | ||
| 50 | entry, next, __kuid_val(parent)) { | ||
| 51 | if (entry->parent_kuid == __kuid_val(parent)) { | ||
| 52 | rcu_read_unlock(); | ||
| 53 | return true; | ||
| 54 | } | ||
| 55 | } | ||
| 56 | rcu_read_unlock(); | ||
| 57 | |||
| 58 | return false; | ||
| 59 | } | ||
| 60 | |||
| 61 | static bool check_setuid_policy_hashtable_key_value(kuid_t parent, | ||
| 62 | kuid_t child) | ||
| 63 | { | ||
| 64 | struct entry *entry; | ||
| 65 | |||
| 66 | rcu_read_lock(); | ||
| 67 | hash_for_each_possible_rcu(safesetid_whitelist_hashtable, | ||
| 68 | entry, next, __kuid_val(parent)) { | ||
| 69 | if (entry->parent_kuid == __kuid_val(parent) && | ||
| 70 | entry->child_kuid == __kuid_val(child)) { | ||
| 71 | rcu_read_unlock(); | ||
| 72 | return true; | ||
| 73 | } | ||
| 74 | } | ||
| 75 | rcu_read_unlock(); | ||
| 76 | |||
| 77 | return false; | ||
| 78 | } | ||
| 79 | |||
| 80 | static int safesetid_security_capable(const struct cred *cred, | ||
| 81 | struct user_namespace *ns, | ||
| 82 | int cap, | ||
| 83 | unsigned int opts) | ||
| 84 | { | ||
| 85 | if (cap == CAP_SETUID && | ||
| 86 | check_setuid_policy_hashtable_key(cred->uid)) { | ||
| 87 | if (!(opts & CAP_OPT_INSETID)) { | ||
| 88 | /* | ||
| 89 | * Deny if we're not in a set*uid() syscall to avoid | ||
| 90 | * giving powers gated by CAP_SETUID that are related | ||
| 91 | * to functionality other than calling set*uid() (e.g. | ||
| 92 | * allowing user to set up userns uid mappings). | ||
| 93 | */ | ||
| 94 | pr_warn("Operation requires CAP_SETUID, which is not available to UID %u for operations besides approved set*uid transitions", | ||
| 95 | __kuid_val(cred->uid)); | ||
| 96 | return -1; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | static int check_uid_transition(kuid_t parent, kuid_t child) | ||
| 103 | { | ||
| 104 | if (check_setuid_policy_hashtable_key_value(parent, child)) | ||
| 105 | return 0; | ||
| 106 | pr_warn("UID transition (%d -> %d) blocked", | ||
| 107 | __kuid_val(parent), | ||
| 108 | __kuid_val(child)); | ||
| 109 | /* | ||
| 110 | * Kill this process to avoid potential security vulnerabilities | ||
| 111 | * that could arise from a missing whitelist entry preventing a | ||
| 112 | * privileged process from dropping to a lesser-privileged one. | ||
| 113 | */ | ||
| 114 | force_sig(SIGKILL, current); | ||
| 115 | return -EACCES; | ||
| 116 | } | ||
| 117 | |||
| 118 | /* | ||
| 119 | * Check whether there is either an exception for user under old cred struct to | ||
| 120 | * set*uid to user under new cred struct, or the UID transition is allowed (by | ||
| 121 | * Linux set*uid rules) even without CAP_SETUID. | ||
| 122 | */ | ||
| 123 | static int safesetid_task_fix_setuid(struct cred *new, | ||
| 124 | const struct cred *old, | ||
| 125 | int flags) | ||
| 126 | { | ||
| 127 | |||
| 128 | /* Do nothing if there are no setuid restrictions for this UID. */ | ||
| 129 | if (!check_setuid_policy_hashtable_key(old->uid)) | ||
| 130 | return 0; | ||
| 131 | |||
| 132 | switch (flags) { | ||
| 133 | case LSM_SETID_RE: | ||
| 134 | /* | ||
| 135 | * Users for which setuid restrictions exist can only set the | ||
| 136 | * real UID to the real UID or the effective UID, unless an | ||
| 137 | * explicit whitelist policy allows the transition. | ||
| 138 | */ | ||
| 139 | if (!uid_eq(old->uid, new->uid) && | ||
| 140 | !uid_eq(old->euid, new->uid)) { | ||
| 141 | return check_uid_transition(old->uid, new->uid); | ||
| 142 | } | ||
| 143 | /* | ||
| 144 | * Users for which setuid restrictions exist can only set the | ||
| 145 | * effective UID to the real UID, the effective UID, or the | ||
| 146 | * saved set-UID, unless an explicit whitelist policy allows | ||
| 147 | * the transition. | ||
| 148 | */ | ||
| 149 | if (!uid_eq(old->uid, new->euid) && | ||
| 150 | !uid_eq(old->euid, new->euid) && | ||
| 151 | !uid_eq(old->suid, new->euid)) { | ||
| 152 | return check_uid_transition(old->euid, new->euid); | ||
| 153 | } | ||
| 154 | break; | ||
| 155 | case LSM_SETID_ID: | ||
| 156 | /* | ||
| 157 | * Users for which setuid restrictions exist cannot change the | ||
| 158 | * real UID or saved set-UID unless an explicit whitelist | ||
| 159 | * policy allows the transition. | ||
| 160 | */ | ||
| 161 | if (!uid_eq(old->uid, new->uid)) | ||
| 162 | return check_uid_transition(old->uid, new->uid); | ||
| 163 | if (!uid_eq(old->suid, new->suid)) | ||
| 164 | return check_uid_transition(old->suid, new->suid); | ||
| 165 | break; | ||
| 166 | case LSM_SETID_RES: | ||
| 167 | /* | ||
| 168 | * Users for which setuid restrictions exist cannot change the | ||
| 169 | * real UID, effective UID, or saved set-UID to anything but | ||
| 170 | * one of: the current real UID, the current effective UID or | ||
| 171 | * the current saved set-user-ID unless an explicit whitelist | ||
| 172 | * policy allows the transition. | ||
| 173 | */ | ||
| 174 | if (!uid_eq(new->uid, old->uid) && | ||
| 175 | !uid_eq(new->uid, old->euid) && | ||
| 176 | !uid_eq(new->uid, old->suid)) { | ||
| 177 | return check_uid_transition(old->uid, new->uid); | ||
| 178 | } | ||
| 179 | if (!uid_eq(new->euid, old->uid) && | ||
| 180 | !uid_eq(new->euid, old->euid) && | ||
| 181 | !uid_eq(new->euid, old->suid)) { | ||
| 182 | return check_uid_transition(old->euid, new->euid); | ||
| 183 | } | ||
| 184 | if (!uid_eq(new->suid, old->uid) && | ||
| 185 | !uid_eq(new->suid, old->euid) && | ||
| 186 | !uid_eq(new->suid, old->suid)) { | ||
| 187 | return check_uid_transition(old->suid, new->suid); | ||
| 188 | } | ||
| 189 | break; | ||
| 190 | case LSM_SETID_FS: | ||
| 191 | /* | ||
| 192 | * Users for which setuid restrictions exist cannot change the | ||
| 193 | * filesystem UID to anything but one of: the current real UID, | ||
| 194 | * the current effective UID or the current saved set-UID | ||
| 195 | * unless an explicit whitelist policy allows the transition. | ||
| 196 | */ | ||
| 197 | if (!uid_eq(new->fsuid, old->uid) && | ||
| 198 | !uid_eq(new->fsuid, old->euid) && | ||
| 199 | !uid_eq(new->fsuid, old->suid) && | ||
| 200 | !uid_eq(new->fsuid, old->fsuid)) { | ||
| 201 | return check_uid_transition(old->fsuid, new->fsuid); | ||
| 202 | } | ||
| 203 | break; | ||
| 204 | default: | ||
| 205 | pr_warn("Unknown setid state %d\n", flags); | ||
| 206 | force_sig(SIGKILL, current); | ||
| 207 | return -EINVAL; | ||
| 208 | } | ||
| 209 | return 0; | ||
| 210 | } | ||
| 211 | |||
| 212 | int add_safesetid_whitelist_entry(kuid_t parent, kuid_t child) | ||
| 213 | { | ||
| 214 | struct entry *new; | ||
| 215 | |||
| 216 | /* Return if entry already exists */ | ||
| 217 | if (check_setuid_policy_hashtable_key_value(parent, child)) | ||
| 218 | return 0; | ||
| 219 | |||
| 220 | new = kzalloc(sizeof(struct entry), GFP_KERNEL); | ||
| 221 | if (!new) | ||
| 222 | return -ENOMEM; | ||
| 223 | new->parent_kuid = __kuid_val(parent); | ||
| 224 | new->child_kuid = __kuid_val(child); | ||
| 225 | spin_lock(&safesetid_whitelist_hashtable_spinlock); | ||
| 226 | hash_add_rcu(safesetid_whitelist_hashtable, | ||
| 227 | &new->next, | ||
| 228 | __kuid_val(parent)); | ||
| 229 | spin_unlock(&safesetid_whitelist_hashtable_spinlock); | ||
| 230 | return 0; | ||
| 231 | } | ||
| 232 | |||
| 233 | void flush_safesetid_whitelist_entries(void) | ||
| 234 | { | ||
| 235 | struct entry *entry; | ||
| 236 | struct hlist_node *hlist_node; | ||
| 237 | unsigned int bkt_loop_cursor; | ||
| 238 | HLIST_HEAD(free_list); | ||
| 239 | |||
| 240 | /* | ||
| 241 | * Could probably use hash_for_each_rcu here instead, but this should | ||
| 242 | * be fine as well. | ||
| 243 | */ | ||
| 244 | spin_lock(&safesetid_whitelist_hashtable_spinlock); | ||
| 245 | hash_for_each_safe(safesetid_whitelist_hashtable, bkt_loop_cursor, | ||
| 246 | hlist_node, entry, next) { | ||
| 247 | hash_del_rcu(&entry->next); | ||
| 248 | hlist_add_head(&entry->dlist, &free_list); | ||
| 249 | } | ||
| 250 | spin_unlock(&safesetid_whitelist_hashtable_spinlock); | ||
| 251 | synchronize_rcu(); | ||
| 252 | hlist_for_each_entry_safe(entry, hlist_node, &free_list, dlist) { | ||
| 253 | hlist_del(&entry->dlist); | ||
| 254 | kfree(entry); | ||
| 255 | } | ||
| 256 | } | ||
| 257 | |||
| 258 | static struct security_hook_list safesetid_security_hooks[] = { | ||
| 259 | LSM_HOOK_INIT(task_fix_setuid, safesetid_task_fix_setuid), | ||
| 260 | LSM_HOOK_INIT(capable, safesetid_security_capable) | ||
| 261 | }; | ||
| 262 | |||
| 263 | static int __init safesetid_security_init(void) | ||
| 264 | { | ||
| 265 | security_add_hooks(safesetid_security_hooks, | ||
| 266 | ARRAY_SIZE(safesetid_security_hooks), "safesetid"); | ||
| 267 | |||
| 268 | /* Report that SafeSetID successfully initialized */ | ||
| 269 | safesetid_initialized = 1; | ||
| 270 | |||
| 271 | return 0; | ||
| 272 | } | ||
| 273 | |||
| 274 | DEFINE_LSM(safesetid_security_init) = { | ||
| 275 | .init = safesetid_security_init, | ||
| 276 | .name = "safesetid", | ||
| 277 | }; | ||
diff --git a/security/safesetid/lsm.h b/security/safesetid/lsm.h new file mode 100644 index 000000000000..c1ea3c265fcf --- /dev/null +++ b/security/safesetid/lsm.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * SafeSetID Linux Security Module | ||
| 4 | * | ||
| 5 | * Author: Micah Morton <mortonm@chromium.org> | ||
| 6 | * | ||
| 7 | * Copyright (C) 2018 The Chromium OS Authors. | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2, as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | #ifndef _SAFESETID_H | ||
| 15 | #define _SAFESETID_H | ||
| 16 | |||
| 17 | #include <linux/types.h> | ||
| 18 | |||
| 19 | /* Flag indicating whether initialization completed */ | ||
| 20 | extern int safesetid_initialized; | ||
| 21 | |||
| 22 | /* Function type. */ | ||
| 23 | enum safesetid_whitelist_file_write_type { | ||
| 24 | SAFESETID_WHITELIST_ADD, /* Add whitelist policy. */ | ||
| 25 | SAFESETID_WHITELIST_FLUSH, /* Flush whitelist policies. */ | ||
| 26 | }; | ||
| 27 | |||
| 28 | /* Add entry to safesetid whitelist to allow 'parent' to setid to 'child'. */ | ||
| 29 | int add_safesetid_whitelist_entry(kuid_t parent, kuid_t child); | ||
| 30 | |||
| 31 | void flush_safesetid_whitelist_entries(void); | ||
| 32 | |||
| 33 | #endif /* _SAFESETID_H */ | ||
diff --git a/security/safesetid/securityfs.c b/security/safesetid/securityfs.c new file mode 100644 index 000000000000..2c6c829be044 --- /dev/null +++ b/security/safesetid/securityfs.c | |||
| @@ -0,0 +1,193 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * SafeSetID Linux Security Module | ||
| 4 | * | ||
| 5 | * Author: Micah Morton <mortonm@chromium.org> | ||
| 6 | * | ||
| 7 | * Copyright (C) 2018 The Chromium OS Authors. | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2, as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | #include <linux/security.h> | ||
| 15 | #include <linux/cred.h> | ||
| 16 | |||
| 17 | #include "lsm.h" | ||
| 18 | |||
| 19 | static struct dentry *safesetid_policy_dir; | ||
| 20 | |||
| 21 | struct safesetid_file_entry { | ||
| 22 | const char *name; | ||
| 23 | enum safesetid_whitelist_file_write_type type; | ||
| 24 | struct dentry *dentry; | ||
| 25 | }; | ||
| 26 | |||
| 27 | static struct safesetid_file_entry safesetid_files[] = { | ||
| 28 | {.name = "add_whitelist_policy", | ||
| 29 | .type = SAFESETID_WHITELIST_ADD}, | ||
| 30 | {.name = "flush_whitelist_policies", | ||
| 31 | .type = SAFESETID_WHITELIST_FLUSH}, | ||
| 32 | }; | ||
| 33 | |||
| 34 | /* | ||
| 35 | * In the case the input buffer contains one or more invalid UIDs, the kuid_t | ||
| 36 | * variables pointed to by 'parent' and 'child' will get updated but this | ||
| 37 | * function will return an error. | ||
| 38 | */ | ||
| 39 | static int parse_safesetid_whitelist_policy(const char __user *buf, | ||
| 40 | size_t len, | ||
| 41 | kuid_t *parent, | ||
| 42 | kuid_t *child) | ||
| 43 | { | ||
| 44 | char *kern_buf; | ||
| 45 | char *parent_buf; | ||
| 46 | char *child_buf; | ||
| 47 | const char separator[] = ":"; | ||
| 48 | int ret; | ||
| 49 | size_t first_substring_length; | ||
| 50 | long parsed_parent; | ||
| 51 | long parsed_child; | ||
| 52 | |||
| 53 | /* Duplicate string from user memory and NULL-terminate */ | ||
| 54 | kern_buf = memdup_user_nul(buf, len); | ||
| 55 | if (IS_ERR(kern_buf)) | ||
| 56 | return PTR_ERR(kern_buf); | ||
| 57 | |||
| 58 | /* | ||
| 59 | * Format of |buf| string should be <UID>:<UID>. | ||
| 60 | * Find location of ":" in kern_buf (copied from |buf|). | ||
| 61 | */ | ||
| 62 | first_substring_length = strcspn(kern_buf, separator); | ||
| 63 | if (first_substring_length == 0 || first_substring_length == len) { | ||
| 64 | ret = -EINVAL; | ||
| 65 | goto free_kern; | ||
| 66 | } | ||
| 67 | |||
| 68 | parent_buf = kmemdup_nul(kern_buf, first_substring_length, GFP_KERNEL); | ||
| 69 | if (!parent_buf) { | ||
| 70 | ret = -ENOMEM; | ||
| 71 | goto free_kern; | ||
| 72 | } | ||
| 73 | |||
| 74 | ret = kstrtol(parent_buf, 0, &parsed_parent); | ||
| 75 | if (ret) | ||
| 76 | goto free_both; | ||
| 77 | |||
| 78 | child_buf = kern_buf + first_substring_length + 1; | ||
| 79 | ret = kstrtol(child_buf, 0, &parsed_child); | ||
| 80 | if (ret) | ||
| 81 | goto free_both; | ||
| 82 | |||
| 83 | *parent = make_kuid(current_user_ns(), parsed_parent); | ||
| 84 | if (!uid_valid(*parent)) { | ||
| 85 | ret = -EINVAL; | ||
| 86 | goto free_both; | ||
| 87 | } | ||
| 88 | |||
| 89 | *child = make_kuid(current_user_ns(), parsed_child); | ||
| 90 | if (!uid_valid(*child)) { | ||
| 91 | ret = -EINVAL; | ||
| 92 | goto free_both; | ||
| 93 | } | ||
| 94 | |||
| 95 | free_both: | ||
| 96 | kfree(parent_buf); | ||
| 97 | free_kern: | ||
| 98 | kfree(kern_buf); | ||
| 99 | return ret; | ||
| 100 | } | ||
| 101 | |||
| 102 | static ssize_t safesetid_file_write(struct file *file, | ||
| 103 | const char __user *buf, | ||
| 104 | size_t len, | ||
| 105 | loff_t *ppos) | ||
| 106 | { | ||
| 107 | struct safesetid_file_entry *file_entry = | ||
| 108 | file->f_inode->i_private; | ||
| 109 | kuid_t parent; | ||
| 110 | kuid_t child; | ||
| 111 | int ret; | ||
| 112 | |||
| 113 | if (!ns_capable(current_user_ns(), CAP_MAC_ADMIN)) | ||
| 114 | return -EPERM; | ||
| 115 | |||
| 116 | if (*ppos != 0) | ||
| 117 | return -EINVAL; | ||
| 118 | |||
| 119 | switch (file_entry->type) { | ||
| 120 | case SAFESETID_WHITELIST_FLUSH: | ||
| 121 | flush_safesetid_whitelist_entries(); | ||
| 122 | break; | ||
| 123 | case SAFESETID_WHITELIST_ADD: | ||
| 124 | ret = parse_safesetid_whitelist_policy(buf, len, &parent, | ||
| 125 | &child); | ||
| 126 | if (ret) | ||
| 127 | return ret; | ||
| 128 | |||
| 129 | ret = add_safesetid_whitelist_entry(parent, child); | ||
| 130 | if (ret) | ||
| 131 | return ret; | ||
| 132 | break; | ||
| 133 | default: | ||
| 134 | pr_warn("Unknown securityfs file %d\n", file_entry->type); | ||
| 135 | break; | ||
| 136 | } | ||
| 137 | |||
| 138 | /* Return len on success so caller won't keep trying to write */ | ||
| 139 | return len; | ||
| 140 | } | ||
| 141 | |||
| 142 | static const struct file_operations safesetid_file_fops = { | ||
| 143 | .write = safesetid_file_write, | ||
| 144 | }; | ||
| 145 | |||
| 146 | static void safesetid_shutdown_securityfs(void) | ||
| 147 | { | ||
| 148 | int i; | ||
| 149 | |||
| 150 | for (i = 0; i < ARRAY_SIZE(safesetid_files); ++i) { | ||
| 151 | struct safesetid_file_entry *entry = | ||
| 152 | &safesetid_files[i]; | ||
| 153 | securityfs_remove(entry->dentry); | ||
| 154 | entry->dentry = NULL; | ||
| 155 | } | ||
| 156 | |||
| 157 | securityfs_remove(safesetid_policy_dir); | ||
| 158 | safesetid_policy_dir = NULL; | ||
| 159 | } | ||
| 160 | |||
| 161 | static int __init safesetid_init_securityfs(void) | ||
| 162 | { | ||
| 163 | int i; | ||
| 164 | int ret; | ||
| 165 | |||
| 166 | if (!safesetid_initialized) | ||
| 167 | return 0; | ||
| 168 | |||
| 169 | safesetid_policy_dir = securityfs_create_dir("safesetid", NULL); | ||
| 170 | if (IS_ERR(safesetid_policy_dir)) { | ||
| 171 | ret = PTR_ERR(safesetid_policy_dir); | ||
| 172 | goto error; | ||
| 173 | } | ||
| 174 | |||
| 175 | for (i = 0; i < ARRAY_SIZE(safesetid_files); ++i) { | ||
| 176 | struct safesetid_file_entry *entry = | ||
| 177 | &safesetid_files[i]; | ||
| 178 | entry->dentry = securityfs_create_file( | ||
| 179 | entry->name, 0200, safesetid_policy_dir, | ||
| 180 | entry, &safesetid_file_fops); | ||
| 181 | if (IS_ERR(entry->dentry)) { | ||
| 182 | ret = PTR_ERR(entry->dentry); | ||
| 183 | goto error; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | return 0; | ||
| 188 | |||
| 189 | error: | ||
| 190 | safesetid_shutdown_securityfs(); | ||
| 191 | return ret; | ||
| 192 | } | ||
| 193 | fs_initcall(safesetid_init_securityfs); | ||
diff --git a/security/security.c b/security/security.c index 55bc49027ba9..ed9b8cbf21cf 100644 --- a/security/security.c +++ b/security/security.c | |||
| @@ -30,20 +30,32 @@ | |||
| 30 | #include <linux/personality.h> | 30 | #include <linux/personality.h> |
| 31 | #include <linux/backing-dev.h> | 31 | #include <linux/backing-dev.h> |
| 32 | #include <linux/string.h> | 32 | #include <linux/string.h> |
| 33 | #include <linux/msg.h> | ||
| 33 | #include <net/flow.h> | 34 | #include <net/flow.h> |
| 34 | 35 | ||
| 35 | #define MAX_LSM_EVM_XATTR 2 | 36 | #define MAX_LSM_EVM_XATTR 2 |
| 36 | 37 | ||
| 37 | /* Maximum number of letters for an LSM name string */ | 38 | /* How many LSMs were built into the kernel? */ |
| 38 | #define SECURITY_NAME_MAX 10 | 39 | #define LSM_COUNT (__end_lsm_info - __start_lsm_info) |
| 39 | 40 | ||
| 40 | struct security_hook_heads security_hook_heads __lsm_ro_after_init; | 41 | struct security_hook_heads security_hook_heads __lsm_ro_after_init; |
| 41 | static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain); | 42 | static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain); |
| 42 | 43 | ||
| 44 | static struct kmem_cache *lsm_file_cache; | ||
| 45 | static struct kmem_cache *lsm_inode_cache; | ||
| 46 | |||
| 43 | char *lsm_names; | 47 | char *lsm_names; |
| 48 | static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init; | ||
| 49 | |||
| 44 | /* Boot-time LSM user choice */ | 50 | /* Boot-time LSM user choice */ |
| 45 | static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = | 51 | static __initdata const char *chosen_lsm_order; |
| 46 | CONFIG_DEFAULT_SECURITY; | 52 | static __initdata const char *chosen_major_lsm; |
| 53 | |||
| 54 | static __initconst const char * const builtin_lsm_order = CONFIG_LSM; | ||
| 55 | |||
| 56 | /* Ordered list of LSMs to initialize. */ | ||
| 57 | static __initdata struct lsm_info **ordered_lsms; | ||
| 58 | static __initdata struct lsm_info *exclusive; | ||
| 47 | 59 | ||
| 48 | static __initdata bool debug; | 60 | static __initdata bool debug; |
| 49 | #define init_debug(...) \ | 61 | #define init_debug(...) \ |
| @@ -52,18 +64,269 @@ static __initdata bool debug; | |||
| 52 | pr_info(__VA_ARGS__); \ | 64 | pr_info(__VA_ARGS__); \ |
| 53 | } while (0) | 65 | } while (0) |
| 54 | 66 | ||
| 55 | static void __init major_lsm_init(void) | 67 | static bool __init is_enabled(struct lsm_info *lsm) |
| 56 | { | 68 | { |
| 57 | struct lsm_info *lsm; | 69 | if (!lsm->enabled) |
| 58 | int ret; | 70 | return false; |
| 71 | |||
| 72 | return *lsm->enabled; | ||
| 73 | } | ||
| 74 | |||
| 75 | /* Mark an LSM's enabled flag. */ | ||
| 76 | static int lsm_enabled_true __initdata = 1; | ||
| 77 | static int lsm_enabled_false __initdata = 0; | ||
| 78 | static void __init set_enabled(struct lsm_info *lsm, bool enabled) | ||
| 79 | { | ||
| 80 | /* | ||
| 81 | * When an LSM hasn't configured an enable variable, we can use | ||
| 82 | * a hard-coded location for storing the default enabled state. | ||
| 83 | */ | ||
| 84 | if (!lsm->enabled) { | ||
| 85 | if (enabled) | ||
| 86 | lsm->enabled = &lsm_enabled_true; | ||
| 87 | else | ||
| 88 | lsm->enabled = &lsm_enabled_false; | ||
| 89 | } else if (lsm->enabled == &lsm_enabled_true) { | ||
| 90 | if (!enabled) | ||
| 91 | lsm->enabled = &lsm_enabled_false; | ||
| 92 | } else if (lsm->enabled == &lsm_enabled_false) { | ||
| 93 | if (enabled) | ||
| 94 | lsm->enabled = &lsm_enabled_true; | ||
| 95 | } else { | ||
| 96 | *lsm->enabled = enabled; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | /* Is an LSM already listed in the ordered LSMs list? */ | ||
| 101 | static bool __init exists_ordered_lsm(struct lsm_info *lsm) | ||
| 102 | { | ||
| 103 | struct lsm_info **check; | ||
| 104 | |||
| 105 | for (check = ordered_lsms; *check; check++) | ||
| 106 | if (*check == lsm) | ||
| 107 | return true; | ||
| 108 | |||
| 109 | return false; | ||
| 110 | } | ||
| 111 | |||
| 112 | /* Append an LSM to the list of ordered LSMs to initialize. */ | ||
| 113 | static int last_lsm __initdata; | ||
| 114 | static void __init append_ordered_lsm(struct lsm_info *lsm, const char *from) | ||
| 115 | { | ||
| 116 | /* Ignore duplicate selections. */ | ||
| 117 | if (exists_ordered_lsm(lsm)) | ||
| 118 | return; | ||
| 119 | |||
| 120 | if (WARN(last_lsm == LSM_COUNT, "%s: out of LSM slots!?\n", from)) | ||
| 121 | return; | ||
| 122 | |||
| 123 | /* Enable this LSM, if it is not already set. */ | ||
| 124 | if (!lsm->enabled) | ||
| 125 | lsm->enabled = &lsm_enabled_true; | ||
| 126 | ordered_lsms[last_lsm++] = lsm; | ||
| 127 | |||
| 128 | init_debug("%s ordering: %s (%sabled)\n", from, lsm->name, | ||
| 129 | is_enabled(lsm) ? "en" : "dis"); | ||
| 130 | } | ||
| 131 | |||
| 132 | /* Is an LSM allowed to be initialized? */ | ||
| 133 | static bool __init lsm_allowed(struct lsm_info *lsm) | ||
| 134 | { | ||
| 135 | /* Skip if the LSM is disabled. */ | ||
| 136 | if (!is_enabled(lsm)) | ||
| 137 | return false; | ||
| 138 | |||
| 139 | /* Not allowed if another exclusive LSM already initialized. */ | ||
| 140 | if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && exclusive) { | ||
| 141 | init_debug("exclusive disabled: %s\n", lsm->name); | ||
| 142 | return false; | ||
| 143 | } | ||
| 144 | |||
| 145 | return true; | ||
| 146 | } | ||
| 147 | |||
| 148 | static void __init lsm_set_blob_size(int *need, int *lbs) | ||
| 149 | { | ||
| 150 | int offset; | ||
| 151 | |||
| 152 | if (*need > 0) { | ||
| 153 | offset = *lbs; | ||
| 154 | *lbs += *need; | ||
| 155 | *need = offset; | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 159 | static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed) | ||
| 160 | { | ||
| 161 | if (!needed) | ||
| 162 | return; | ||
| 163 | |||
| 164 | lsm_set_blob_size(&needed->lbs_cred, &blob_sizes.lbs_cred); | ||
| 165 | lsm_set_blob_size(&needed->lbs_file, &blob_sizes.lbs_file); | ||
| 166 | /* | ||
| 167 | * The inode blob gets an rcu_head in addition to | ||
| 168 | * what the modules might need. | ||
| 169 | */ | ||
| 170 | if (needed->lbs_inode && blob_sizes.lbs_inode == 0) | ||
| 171 | blob_sizes.lbs_inode = sizeof(struct rcu_head); | ||
| 172 | lsm_set_blob_size(&needed->lbs_inode, &blob_sizes.lbs_inode); | ||
| 173 | lsm_set_blob_size(&needed->lbs_ipc, &blob_sizes.lbs_ipc); | ||
| 174 | lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg); | ||
| 175 | lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task); | ||
| 176 | } | ||
| 177 | |||
| 178 | /* Prepare LSM for initialization. */ | ||
| 179 | static void __init prepare_lsm(struct lsm_info *lsm) | ||
| 180 | { | ||
| 181 | int enabled = lsm_allowed(lsm); | ||
| 182 | |||
| 183 | /* Record enablement (to handle any following exclusive LSMs). */ | ||
| 184 | set_enabled(lsm, enabled); | ||
| 185 | |||
| 186 | /* If enabled, do pre-initialization work. */ | ||
| 187 | if (enabled) { | ||
| 188 | if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && !exclusive) { | ||
| 189 | exclusive = lsm; | ||
| 190 | init_debug("exclusive chosen: %s\n", lsm->name); | ||
| 191 | } | ||
| 192 | |||
| 193 | lsm_set_blob_sizes(lsm->blobs); | ||
| 194 | } | ||
| 195 | } | ||
| 196 | |||
| 197 | /* Initialize a given LSM, if it is enabled. */ | ||
| 198 | static void __init initialize_lsm(struct lsm_info *lsm) | ||
| 199 | { | ||
| 200 | if (is_enabled(lsm)) { | ||
| 201 | int ret; | ||
| 59 | 202 | ||
| 60 | for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { | ||
| 61 | init_debug("initializing %s\n", lsm->name); | 203 | init_debug("initializing %s\n", lsm->name); |
| 62 | ret = lsm->init(); | 204 | ret = lsm->init(); |
| 63 | WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret); | 205 | WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret); |
| 64 | } | 206 | } |
| 65 | } | 207 | } |
| 66 | 208 | ||
| 209 | /* Populate ordered LSMs list from comma-separated LSM name list. */ | ||
| 210 | static void __init ordered_lsm_parse(const char *order, const char *origin) | ||
| 211 | { | ||
| 212 | struct lsm_info *lsm; | ||
| 213 | char *sep, *name, *next; | ||
| 214 | |||
| 215 | /* LSM_ORDER_FIRST is always first. */ | ||
| 216 | for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { | ||
| 217 | if (lsm->order == LSM_ORDER_FIRST) | ||
| 218 | append_ordered_lsm(lsm, "first"); | ||
| 219 | } | ||
| 220 | |||
| 221 | /* Process "security=", if given. */ | ||
| 222 | if (chosen_major_lsm) { | ||
| 223 | struct lsm_info *major; | ||
| 224 | |||
| 225 | /* | ||
| 226 | * To match the original "security=" behavior, this | ||
| 227 | * explicitly does NOT fallback to another Legacy Major | ||
| 228 | * if the selected one was separately disabled: disable | ||
| 229 | * all non-matching Legacy Major LSMs. | ||
| 230 | */ | ||
| 231 | for (major = __start_lsm_info; major < __end_lsm_info; | ||
| 232 | major++) { | ||
| 233 | if ((major->flags & LSM_FLAG_LEGACY_MAJOR) && | ||
| 234 | strcmp(major->name, chosen_major_lsm) != 0) { | ||
| 235 | set_enabled(major, false); | ||
| 236 | init_debug("security=%s disabled: %s\n", | ||
| 237 | chosen_major_lsm, major->name); | ||
| 238 | } | ||
| 239 | } | ||
| 240 | } | ||
| 241 | |||
| 242 | sep = kstrdup(order, GFP_KERNEL); | ||
| 243 | next = sep; | ||
| 244 | /* Walk the list, looking for matching LSMs. */ | ||
| 245 | while ((name = strsep(&next, ",")) != NULL) { | ||
| 246 | bool found = false; | ||
| 247 | |||
| 248 | for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { | ||
| 249 | if (lsm->order == LSM_ORDER_MUTABLE && | ||
| 250 | strcmp(lsm->name, name) == 0) { | ||
| 251 | append_ordered_lsm(lsm, origin); | ||
| 252 | found = true; | ||
| 253 | } | ||
| 254 | } | ||
| 255 | |||
| 256 | if (!found) | ||
| 257 | init_debug("%s ignored: %s\n", origin, name); | ||
| 258 | } | ||
| 259 | |||
| 260 | /* Process "security=", if given. */ | ||
| 261 | if (chosen_major_lsm) { | ||
| 262 | for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { | ||
| 263 | if (exists_ordered_lsm(lsm)) | ||
| 264 | continue; | ||
| 265 | if (strcmp(lsm->name, chosen_major_lsm) == 0) | ||
| 266 | append_ordered_lsm(lsm, "security="); | ||
| 267 | } | ||
| 268 | } | ||
| 269 | |||
| 270 | /* Disable all LSMs not in the ordered list. */ | ||
| 271 | for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { | ||
| 272 | if (exists_ordered_lsm(lsm)) | ||
| 273 | continue; | ||
| 274 | set_enabled(lsm, false); | ||
| 275 | init_debug("%s disabled: %s\n", origin, lsm->name); | ||
| 276 | } | ||
| 277 | |||
| 278 | kfree(sep); | ||
| 279 | } | ||
| 280 | |||
| 281 | static void __init lsm_early_cred(struct cred *cred); | ||
| 282 | static void __init lsm_early_task(struct task_struct *task); | ||
| 283 | |||
| 284 | static void __init ordered_lsm_init(void) | ||
| 285 | { | ||
| 286 | struct lsm_info **lsm; | ||
| 287 | |||
| 288 | ordered_lsms = kcalloc(LSM_COUNT + 1, sizeof(*ordered_lsms), | ||
| 289 | GFP_KERNEL); | ||
| 290 | |||
| 291 | if (chosen_lsm_order) { | ||
| 292 | if (chosen_major_lsm) { | ||
| 293 | pr_info("security= is ignored because it is superseded by lsm=\n"); | ||
| 294 | chosen_major_lsm = NULL; | ||
| 295 | } | ||
| 296 | ordered_lsm_parse(chosen_lsm_order, "cmdline"); | ||
| 297 | } else | ||
| 298 | ordered_lsm_parse(builtin_lsm_order, "builtin"); | ||
| 299 | |||
| 300 | for (lsm = ordered_lsms; *lsm; lsm++) | ||
| 301 | prepare_lsm(*lsm); | ||
| 302 | |||
| 303 | init_debug("cred blob size = %d\n", blob_sizes.lbs_cred); | ||
| 304 | init_debug("file blob size = %d\n", blob_sizes.lbs_file); | ||
| 305 | init_debug("inode blob size = %d\n", blob_sizes.lbs_inode); | ||
| 306 | init_debug("ipc blob size = %d\n", blob_sizes.lbs_ipc); | ||
| 307 | init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg); | ||
| 308 | init_debug("task blob size = %d\n", blob_sizes.lbs_task); | ||
| 309 | |||
| 310 | /* | ||
| 311 | * Create any kmem_caches needed for blobs | ||
| 312 | */ | ||
| 313 | if (blob_sizes.lbs_file) | ||
| 314 | lsm_file_cache = kmem_cache_create("lsm_file_cache", | ||
| 315 | blob_sizes.lbs_file, 0, | ||
| 316 | SLAB_PANIC, NULL); | ||
| 317 | if (blob_sizes.lbs_inode) | ||
| 318 | lsm_inode_cache = kmem_cache_create("lsm_inode_cache", | ||
| 319 | blob_sizes.lbs_inode, 0, | ||
| 320 | SLAB_PANIC, NULL); | ||
| 321 | |||
| 322 | lsm_early_cred((struct cred *) current->cred); | ||
| 323 | lsm_early_task(current); | ||
| 324 | for (lsm = ordered_lsms; *lsm; lsm++) | ||
| 325 | initialize_lsm(*lsm); | ||
| 326 | |||
| 327 | kfree(ordered_lsms); | ||
| 328 | } | ||
| 329 | |||
| 67 | /** | 330 | /** |
| 68 | * security_init - initializes the security framework | 331 | * security_init - initializes the security framework |
| 69 | * | 332 | * |
| @@ -80,28 +343,27 @@ int __init security_init(void) | |||
| 80 | i++) | 343 | i++) |
| 81 | INIT_HLIST_HEAD(&list[i]); | 344 | INIT_HLIST_HEAD(&list[i]); |
| 82 | 345 | ||
| 83 | /* | 346 | /* Load LSMs in specified order. */ |
| 84 | * Load minor LSMs, with the capability module always first. | 347 | ordered_lsm_init(); |
| 85 | */ | ||
| 86 | capability_add_hooks(); | ||
| 87 | yama_add_hooks(); | ||
| 88 | loadpin_add_hooks(); | ||
| 89 | |||
| 90 | /* | ||
| 91 | * Load all the remaining security modules. | ||
| 92 | */ | ||
| 93 | major_lsm_init(); | ||
| 94 | 348 | ||
| 95 | return 0; | 349 | return 0; |
| 96 | } | 350 | } |
| 97 | 351 | ||
| 98 | /* Save user chosen LSM */ | 352 | /* Save user chosen LSM */ |
| 99 | static int __init choose_lsm(char *str) | 353 | static int __init choose_major_lsm(char *str) |
| 354 | { | ||
| 355 | chosen_major_lsm = str; | ||
| 356 | return 1; | ||
| 357 | } | ||
| 358 | __setup("security=", choose_major_lsm); | ||
| 359 | |||
| 360 | /* Explicitly choose LSM initialization order. */ | ||
| 361 | static int __init choose_lsm_order(char *str) | ||
| 100 | { | 362 | { |
| 101 | strncpy(chosen_lsm, str, SECURITY_NAME_MAX); | 363 | chosen_lsm_order = str; |
| 102 | return 1; | 364 | return 1; |
| 103 | } | 365 | } |
| 104 | __setup("security=", choose_lsm); | 366 | __setup("lsm=", choose_lsm_order); |
| 105 | 367 | ||
| 106 | /* Enable LSM order debugging. */ | 368 | /* Enable LSM order debugging. */ |
| 107 | static int __init enable_debug(char *str) | 369 | static int __init enable_debug(char *str) |
| @@ -148,29 +410,6 @@ static int lsm_append(char *new, char **result) | |||
| 148 | } | 410 | } |
| 149 | 411 | ||
| 150 | /** | 412 | /** |
| 151 | * security_module_enable - Load given security module on boot ? | ||
| 152 | * @module: the name of the module | ||
| 153 | * | ||
| 154 | * Each LSM must pass this method before registering its own operations | ||
| 155 | * to avoid security registration races. This method may also be used | ||
| 156 | * to check if your LSM is currently loaded during kernel initialization. | ||
| 157 | * | ||
| 158 | * Returns: | ||
| 159 | * | ||
| 160 | * true if: | ||
| 161 | * | ||
| 162 | * - The passed LSM is the one chosen by user at boot time, | ||
| 163 | * - or the passed LSM is configured as the default and the user did not | ||
| 164 | * choose an alternate LSM at boot time. | ||
| 165 | * | ||
| 166 | * Otherwise, return false. | ||
| 167 | */ | ||
| 168 | int __init security_module_enable(const char *module) | ||
| 169 | { | ||
| 170 | return !strcmp(module, chosen_lsm); | ||
| 171 | } | ||
| 172 | |||
| 173 | /** | ||
| 174 | * security_add_hooks - Add a modules hooks to the hook lists. | 413 | * security_add_hooks - Add a modules hooks to the hook lists. |
| 175 | * @hooks: the hooks to add | 414 | * @hooks: the hooks to add |
| 176 | * @count: the number of hooks to add | 415 | * @count: the number of hooks to add |
| @@ -209,6 +448,161 @@ int unregister_lsm_notifier(struct notifier_block *nb) | |||
| 209 | } | 448 | } |
| 210 | EXPORT_SYMBOL(unregister_lsm_notifier); | 449 | EXPORT_SYMBOL(unregister_lsm_notifier); |
| 211 | 450 | ||
| 451 | /** | ||
| 452 | * lsm_cred_alloc - allocate a composite cred blob | ||
| 453 | * @cred: the cred that needs a blob | ||
| 454 | * @gfp: allocation type | ||
| 455 | * | ||
| 456 | * Allocate the cred blob for all the modules | ||
| 457 | * | ||
| 458 | * Returns 0, or -ENOMEM if memory can't be allocated. | ||
| 459 | */ | ||
| 460 | static int lsm_cred_alloc(struct cred *cred, gfp_t gfp) | ||
| 461 | { | ||
| 462 | if (blob_sizes.lbs_cred == 0) { | ||
| 463 | cred->security = NULL; | ||
| 464 | return 0; | ||
| 465 | } | ||
| 466 | |||
| 467 | cred->security = kzalloc(blob_sizes.lbs_cred, gfp); | ||
| 468 | if (cred->security == NULL) | ||
| 469 | return -ENOMEM; | ||
| 470 | return 0; | ||
| 471 | } | ||
| 472 | |||
| 473 | /** | ||
| 474 | * lsm_early_cred - during initialization allocate a composite cred blob | ||
| 475 | * @cred: the cred that needs a blob | ||
| 476 | * | ||
| 477 | * Allocate the cred blob for all the modules | ||
| 478 | */ | ||
| 479 | static void __init lsm_early_cred(struct cred *cred) | ||
| 480 | { | ||
| 481 | int rc = lsm_cred_alloc(cred, GFP_KERNEL); | ||
| 482 | |||
| 483 | if (rc) | ||
| 484 | panic("%s: Early cred alloc failed.\n", __func__); | ||
| 485 | } | ||
| 486 | |||
| 487 | /** | ||
| 488 | * lsm_file_alloc - allocate a composite file blob | ||
| 489 | * @file: the file that needs a blob | ||
| 490 | * | ||
| 491 | * Allocate the file blob for all the modules | ||
| 492 | * | ||
| 493 | * Returns 0, or -ENOMEM if memory can't be allocated. | ||
| 494 | */ | ||
| 495 | static int lsm_file_alloc(struct file *file) | ||
| 496 | { | ||
| 497 | if (!lsm_file_cache) { | ||
| 498 | file->f_security = NULL; | ||
| 499 | return 0; | ||
| 500 | } | ||
| 501 | |||
| 502 | file->f_security = kmem_cache_zalloc(lsm_file_cache, GFP_KERNEL); | ||
| 503 | if (file->f_security == NULL) | ||
| 504 | return -ENOMEM; | ||
| 505 | return 0; | ||
| 506 | } | ||
| 507 | |||
| 508 | /** | ||
| 509 | * lsm_inode_alloc - allocate a composite inode blob | ||
| 510 | * @inode: the inode that needs a blob | ||
| 511 | * | ||
| 512 | * Allocate the inode blob for all the modules | ||
| 513 | * | ||
| 514 | * Returns 0, or -ENOMEM if memory can't be allocated. | ||
| 515 | */ | ||
| 516 | int lsm_inode_alloc(struct inode *inode) | ||
| 517 | { | ||
| 518 | if (!lsm_inode_cache) { | ||
| 519 | inode->i_security = NULL; | ||
| 520 | return 0; | ||
| 521 | } | ||
| 522 | |||
| 523 | inode->i_security = kmem_cache_zalloc(lsm_inode_cache, GFP_NOFS); | ||
| 524 | if (inode->i_security == NULL) | ||
| 525 | return -ENOMEM; | ||
| 526 | return 0; | ||
| 527 | } | ||
| 528 | |||
| 529 | /** | ||
| 530 | * lsm_task_alloc - allocate a composite task blob | ||
| 531 | * @task: the task that needs a blob | ||
| 532 | * | ||
| 533 | * Allocate the task blob for all the modules | ||
| 534 | * | ||
| 535 | * Returns 0, or -ENOMEM if memory can't be allocated. | ||
| 536 | */ | ||
| 537 | static int lsm_task_alloc(struct task_struct *task) | ||
| 538 | { | ||
| 539 | if (blob_sizes.lbs_task == 0) { | ||
| 540 | task->security = NULL; | ||
| 541 | return 0; | ||
| 542 | } | ||
| 543 | |||
| 544 | task->security = kzalloc(blob_sizes.lbs_task, GFP_KERNEL); | ||
| 545 | if (task->security == NULL) | ||
| 546 | return -ENOMEM; | ||
| 547 | return 0; | ||
| 548 | } | ||
| 549 | |||
| 550 | /** | ||
| 551 | * lsm_ipc_alloc - allocate a composite ipc blob | ||
| 552 | * @kip: the ipc that needs a blob | ||
| 553 | * | ||
| 554 | * Allocate the ipc blob for all the modules | ||
| 555 | * | ||
| 556 | * Returns 0, or -ENOMEM if memory can't be allocated. | ||
| 557 | */ | ||
| 558 | static int lsm_ipc_alloc(struct kern_ipc_perm *kip) | ||
| 559 | { | ||
| 560 | if (blob_sizes.lbs_ipc == 0) { | ||
| 561 | kip->security = NULL; | ||
| 562 | return 0; | ||
| 563 | } | ||
| 564 | |||
| 565 | kip->security = kzalloc(blob_sizes.lbs_ipc, GFP_KERNEL); | ||
| 566 | if (kip->security == NULL) | ||
| 567 | return -ENOMEM; | ||
| 568 | return 0; | ||
| 569 | } | ||
| 570 | |||
| 571 | /** | ||
| 572 | * lsm_msg_msg_alloc - allocate a composite msg_msg blob | ||
| 573 | * @mp: the msg_msg that needs a blob | ||
| 574 | * | ||
| 575 | * Allocate the ipc blob for all the modules | ||
| 576 | * | ||
| 577 | * Returns 0, or -ENOMEM if memory can't be allocated. | ||
| 578 | */ | ||
| 579 | static int lsm_msg_msg_alloc(struct msg_msg *mp) | ||
| 580 | { | ||
| 581 | if (blob_sizes.lbs_msg_msg == 0) { | ||
| 582 | mp->security = NULL; | ||
| 583 | return 0; | ||
| 584 | } | ||
| 585 | |||
| 586 | mp->security = kzalloc(blob_sizes.lbs_msg_msg, GFP_KERNEL); | ||
| 587 | if (mp->security == NULL) | ||
| 588 | return -ENOMEM; | ||
| 589 | return 0; | ||
| 590 | } | ||
| 591 | |||
| 592 | /** | ||
| 593 | * lsm_early_task - during initialization allocate a composite task blob | ||
| 594 | * @task: the task that needs a blob | ||
| 595 | * | ||
| 596 | * Allocate the task blob for all the modules | ||
| 597 | */ | ||
| 598 | static void __init lsm_early_task(struct task_struct *task) | ||
| 599 | { | ||
| 600 | int rc = lsm_task_alloc(task); | ||
| 601 | |||
| 602 | if (rc) | ||
| 603 | panic("%s: Early task alloc failed.\n", __func__); | ||
| 604 | } | ||
| 605 | |||
| 212 | /* | 606 | /* |
| 213 | * Hook list operation macros. | 607 | * Hook list operation macros. |
| 214 | * | 608 | * |
| @@ -294,16 +688,12 @@ int security_capset(struct cred *new, const struct cred *old, | |||
| 294 | effective, inheritable, permitted); | 688 | effective, inheritable, permitted); |
| 295 | } | 689 | } |
| 296 | 690 | ||
| 297 | int security_capable(const struct cred *cred, struct user_namespace *ns, | 691 | int security_capable(const struct cred *cred, |
| 298 | int cap) | 692 | struct user_namespace *ns, |
| 693 | int cap, | ||
| 694 | unsigned int opts) | ||
| 299 | { | 695 | { |
| 300 | return call_int_hook(capable, 0, cred, ns, cap, SECURITY_CAP_AUDIT); | 696 | return call_int_hook(capable, 0, cred, ns, cap, opts); |
| 301 | } | ||
| 302 | |||
| 303 | int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns, | ||
| 304 | int cap) | ||
| 305 | { | ||
| 306 | return call_int_hook(capable, 0, cred, ns, cap, SECURITY_CAP_NOAUDIT); | ||
| 307 | } | 697 | } |
| 308 | 698 | ||
| 309 | int security_quotactl(int cmds, int type, int id, struct super_block *sb) | 699 | int security_quotactl(int cmds, int type, int id, struct super_block *sb) |
| @@ -468,14 +858,40 @@ EXPORT_SYMBOL(security_add_mnt_opt); | |||
| 468 | 858 | ||
| 469 | int security_inode_alloc(struct inode *inode) | 859 | int security_inode_alloc(struct inode *inode) |
| 470 | { | 860 | { |
| 471 | inode->i_security = NULL; | 861 | int rc = lsm_inode_alloc(inode); |
| 472 | return call_int_hook(inode_alloc_security, 0, inode); | 862 | |
| 863 | if (unlikely(rc)) | ||
| 864 | return rc; | ||
| 865 | rc = call_int_hook(inode_alloc_security, 0, inode); | ||
| 866 | if (unlikely(rc)) | ||
| 867 | security_inode_free(inode); | ||
| 868 | return rc; | ||
| 869 | } | ||
| 870 | |||
| 871 | static void inode_free_by_rcu(struct rcu_head *head) | ||
| 872 | { | ||
| 873 | /* | ||
| 874 | * The rcu head is at the start of the inode blob | ||
| 875 | */ | ||
| 876 | kmem_cache_free(lsm_inode_cache, head); | ||
| 473 | } | 877 | } |
| 474 | 878 | ||
| 475 | void security_inode_free(struct inode *inode) | 879 | void security_inode_free(struct inode *inode) |
| 476 | { | 880 | { |
| 477 | integrity_inode_free(inode); | 881 | integrity_inode_free(inode); |
| 478 | call_void_hook(inode_free_security, inode); | 882 | call_void_hook(inode_free_security, inode); |
| 883 | /* | ||
| 884 | * The inode may still be referenced in a path walk and | ||
| 885 | * a call to security_inode_permission() can be made | ||
| 886 | * after inode_free_security() is called. Ideally, the VFS | ||
| 887 | * wouldn't do this, but fixing that is a much harder | ||
| 888 | * job. For now, simply free the i_security via RCU, and | ||
| 889 | * leave the current inode->i_security pointer intact. | ||
| 890 | * The inode will be freed after the RCU grace period too. | ||
| 891 | */ | ||
| 892 | if (inode->i_security) | ||
| 893 | call_rcu((struct rcu_head *)inode->i_security, | ||
| 894 | inode_free_by_rcu); | ||
| 479 | } | 895 | } |
| 480 | 896 | ||
| 481 | int security_dentry_init_security(struct dentry *dentry, int mode, | 897 | int security_dentry_init_security(struct dentry *dentry, int mode, |
| @@ -905,12 +1321,27 @@ int security_file_permission(struct file *file, int mask) | |||
| 905 | 1321 | ||
| 906 | int security_file_alloc(struct file *file) | 1322 | int security_file_alloc(struct file *file) |
| 907 | { | 1323 | { |
| 908 | return call_int_hook(file_alloc_security, 0, file); | 1324 | int rc = lsm_file_alloc(file); |
| 1325 | |||
| 1326 | if (rc) | ||
| 1327 | return rc; | ||
| 1328 | rc = call_int_hook(file_alloc_security, 0, file); | ||
| 1329 | if (unlikely(rc)) | ||
| 1330 | security_file_free(file); | ||
| 1331 | return rc; | ||
| 909 | } | 1332 | } |
| 910 | 1333 | ||
| 911 | void security_file_free(struct file *file) | 1334 | void security_file_free(struct file *file) |
| 912 | { | 1335 | { |
| 1336 | void *blob; | ||
| 1337 | |||
| 913 | call_void_hook(file_free_security, file); | 1338 | call_void_hook(file_free_security, file); |
| 1339 | |||
| 1340 | blob = file->f_security; | ||
| 1341 | if (blob) { | ||
| 1342 | file->f_security = NULL; | ||
| 1343 | kmem_cache_free(lsm_file_cache, blob); | ||
| 1344 | } | ||
| 914 | } | 1345 | } |
| 915 | 1346 | ||
| 916 | int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 1347 | int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| @@ -1012,17 +1443,35 @@ int security_file_open(struct file *file) | |||
| 1012 | 1443 | ||
| 1013 | int security_task_alloc(struct task_struct *task, unsigned long clone_flags) | 1444 | int security_task_alloc(struct task_struct *task, unsigned long clone_flags) |
| 1014 | { | 1445 | { |
| 1015 | return call_int_hook(task_alloc, 0, task, clone_flags); | 1446 | int rc = lsm_task_alloc(task); |
| 1447 | |||
| 1448 | if (rc) | ||
| 1449 | return rc; | ||
| 1450 | rc = call_int_hook(task_alloc, 0, task, clone_flags); | ||
| 1451 | if (unlikely(rc)) | ||
| 1452 | security_task_free(task); | ||
| 1453 | return rc; | ||
| 1016 | } | 1454 | } |
| 1017 | 1455 | ||
| 1018 | void security_task_free(struct task_struct *task) | 1456 | void security_task_free(struct task_struct *task) |
| 1019 | { | 1457 | { |
| 1020 | call_void_hook(task_free, task); | 1458 | call_void_hook(task_free, task); |
| 1459 | |||
| 1460 | kfree(task->security); | ||
| 1461 | task->security = NULL; | ||
| 1021 | } | 1462 | } |
| 1022 | 1463 | ||
| 1023 | int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) | 1464 | int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) |
| 1024 | { | 1465 | { |
| 1025 | return call_int_hook(cred_alloc_blank, 0, cred, gfp); | 1466 | int rc = lsm_cred_alloc(cred, gfp); |
| 1467 | |||
| 1468 | if (rc) | ||
| 1469 | return rc; | ||
| 1470 | |||
| 1471 | rc = call_int_hook(cred_alloc_blank, 0, cred, gfp); | ||
| 1472 | if (unlikely(rc)) | ||
| 1473 | security_cred_free(cred); | ||
| 1474 | return rc; | ||
| 1026 | } | 1475 | } |
| 1027 | 1476 | ||
| 1028 | void security_cred_free(struct cred *cred) | 1477 | void security_cred_free(struct cred *cred) |
| @@ -1035,11 +1484,22 @@ void security_cred_free(struct cred *cred) | |||
| 1035 | return; | 1484 | return; |
| 1036 | 1485 | ||
| 1037 | call_void_hook(cred_free, cred); | 1486 | call_void_hook(cred_free, cred); |
| 1487 | |||
| 1488 | kfree(cred->security); | ||
| 1489 | cred->security = NULL; | ||
| 1038 | } | 1490 | } |
| 1039 | 1491 | ||
| 1040 | int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp) | 1492 | int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp) |
| 1041 | { | 1493 | { |
| 1042 | return call_int_hook(cred_prepare, 0, new, old, gfp); | 1494 | int rc = lsm_cred_alloc(new, gfp); |
| 1495 | |||
| 1496 | if (rc) | ||
| 1497 | return rc; | ||
| 1498 | |||
| 1499 | rc = call_int_hook(cred_prepare, 0, new, old, gfp); | ||
| 1500 | if (unlikely(rc)) | ||
| 1501 | security_cred_free(new); | ||
| 1502 | return rc; | ||
| 1043 | } | 1503 | } |
| 1044 | 1504 | ||
| 1045 | void security_transfer_creds(struct cred *new, const struct cred *old) | 1505 | void security_transfer_creds(struct cred *new, const struct cred *old) |
| @@ -1220,22 +1680,40 @@ void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid) | |||
| 1220 | 1680 | ||
| 1221 | int security_msg_msg_alloc(struct msg_msg *msg) | 1681 | int security_msg_msg_alloc(struct msg_msg *msg) |
| 1222 | { | 1682 | { |
| 1223 | return call_int_hook(msg_msg_alloc_security, 0, msg); | 1683 | int rc = lsm_msg_msg_alloc(msg); |
| 1684 | |||
| 1685 | if (unlikely(rc)) | ||
| 1686 | return rc; | ||
| 1687 | rc = call_int_hook(msg_msg_alloc_security, 0, msg); | ||
| 1688 | if (unlikely(rc)) | ||
| 1689 | security_msg_msg_free(msg); | ||
| 1690 | return rc; | ||
| 1224 | } | 1691 | } |
| 1225 | 1692 | ||
| 1226 | void security_msg_msg_free(struct msg_msg *msg) | 1693 | void security_msg_msg_free(struct msg_msg *msg) |
| 1227 | { | 1694 | { |
| 1228 | call_void_hook(msg_msg_free_security, msg); | 1695 | call_void_hook(msg_msg_free_security, msg); |
| 1696 | kfree(msg->security); | ||
| 1697 | msg->security = NULL; | ||
| 1229 | } | 1698 | } |
| 1230 | 1699 | ||
| 1231 | int security_msg_queue_alloc(struct kern_ipc_perm *msq) | 1700 | int security_msg_queue_alloc(struct kern_ipc_perm *msq) |
| 1232 | { | 1701 | { |
| 1233 | return call_int_hook(msg_queue_alloc_security, 0, msq); | 1702 | int rc = lsm_ipc_alloc(msq); |
| 1703 | |||
| 1704 | if (unlikely(rc)) | ||
| 1705 | return rc; | ||
| 1706 | rc = call_int_hook(msg_queue_alloc_security, 0, msq); | ||
| 1707 | if (unlikely(rc)) | ||
| 1708 | security_msg_queue_free(msq); | ||
| 1709 | return rc; | ||
| 1234 | } | 1710 | } |
| 1235 | 1711 | ||
| 1236 | void security_msg_queue_free(struct kern_ipc_perm *msq) | 1712 | void security_msg_queue_free(struct kern_ipc_perm *msq) |
| 1237 | { | 1713 | { |
| 1238 | call_void_hook(msg_queue_free_security, msq); | 1714 | call_void_hook(msg_queue_free_security, msq); |
| 1715 | kfree(msq->security); | ||
| 1716 | msq->security = NULL; | ||
| 1239 | } | 1717 | } |
| 1240 | 1718 | ||
| 1241 | int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) | 1719 | int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) |
| @@ -1262,12 +1740,21 @@ int security_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg, | |||
| 1262 | 1740 | ||
| 1263 | int security_shm_alloc(struct kern_ipc_perm *shp) | 1741 | int security_shm_alloc(struct kern_ipc_perm *shp) |
| 1264 | { | 1742 | { |
| 1265 | return call_int_hook(shm_alloc_security, 0, shp); | 1743 | int rc = lsm_ipc_alloc(shp); |
| 1744 | |||
| 1745 | if (unlikely(rc)) | ||
| 1746 | return rc; | ||
| 1747 | rc = call_int_hook(shm_alloc_security, 0, shp); | ||
| 1748 | if (unlikely(rc)) | ||
| 1749 | security_shm_free(shp); | ||
| 1750 | return rc; | ||
| 1266 | } | 1751 | } |
| 1267 | 1752 | ||
| 1268 | void security_shm_free(struct kern_ipc_perm *shp) | 1753 | void security_shm_free(struct kern_ipc_perm *shp) |
| 1269 | { | 1754 | { |
| 1270 | call_void_hook(shm_free_security, shp); | 1755 | call_void_hook(shm_free_security, shp); |
| 1756 | kfree(shp->security); | ||
| 1757 | shp->security = NULL; | ||
| 1271 | } | 1758 | } |
| 1272 | 1759 | ||
| 1273 | int security_shm_associate(struct kern_ipc_perm *shp, int shmflg) | 1760 | int security_shm_associate(struct kern_ipc_perm *shp, int shmflg) |
| @@ -1287,12 +1774,21 @@ int security_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmf | |||
| 1287 | 1774 | ||
| 1288 | int security_sem_alloc(struct kern_ipc_perm *sma) | 1775 | int security_sem_alloc(struct kern_ipc_perm *sma) |
| 1289 | { | 1776 | { |
| 1290 | return call_int_hook(sem_alloc_security, 0, sma); | 1777 | int rc = lsm_ipc_alloc(sma); |
| 1778 | |||
| 1779 | if (unlikely(rc)) | ||
| 1780 | return rc; | ||
| 1781 | rc = call_int_hook(sem_alloc_security, 0, sma); | ||
| 1782 | if (unlikely(rc)) | ||
| 1783 | security_sem_free(sma); | ||
| 1784 | return rc; | ||
| 1291 | } | 1785 | } |
| 1292 | 1786 | ||
| 1293 | void security_sem_free(struct kern_ipc_perm *sma) | 1787 | void security_sem_free(struct kern_ipc_perm *sma) |
| 1294 | { | 1788 | { |
| 1295 | call_void_hook(sem_free_security, sma); | 1789 | call_void_hook(sem_free_security, sma); |
| 1790 | kfree(sma->security); | ||
| 1791 | sma->security = NULL; | ||
| 1296 | } | 1792 | } |
| 1297 | 1793 | ||
| 1298 | int security_sem_associate(struct kern_ipc_perm *sma, int semflg) | 1794 | int security_sem_associate(struct kern_ipc_perm *sma, int semflg) |
| @@ -1319,14 +1815,30 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode) | |||
| 1319 | } | 1815 | } |
| 1320 | EXPORT_SYMBOL(security_d_instantiate); | 1816 | EXPORT_SYMBOL(security_d_instantiate); |
| 1321 | 1817 | ||
| 1322 | int security_getprocattr(struct task_struct *p, char *name, char **value) | 1818 | int security_getprocattr(struct task_struct *p, const char *lsm, char *name, |
| 1819 | char **value) | ||
| 1323 | { | 1820 | { |
| 1324 | return call_int_hook(getprocattr, -EINVAL, p, name, value); | 1821 | struct security_hook_list *hp; |
| 1822 | |||
| 1823 | hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) { | ||
| 1824 | if (lsm != NULL && strcmp(lsm, hp->lsm)) | ||
| 1825 | continue; | ||
| 1826 | return hp->hook.getprocattr(p, name, value); | ||
| 1827 | } | ||
| 1828 | return -EINVAL; | ||
| 1325 | } | 1829 | } |
| 1326 | 1830 | ||
| 1327 | int security_setprocattr(const char *name, void *value, size_t size) | 1831 | int security_setprocattr(const char *lsm, const char *name, void *value, |
| 1832 | size_t size) | ||
| 1328 | { | 1833 | { |
| 1329 | return call_int_hook(setprocattr, -EINVAL, name, value, size); | 1834 | struct security_hook_list *hp; |
| 1835 | |||
| 1836 | hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) { | ||
| 1837 | if (lsm != NULL && strcmp(lsm, hp->lsm)) | ||
| 1838 | continue; | ||
| 1839 | return hp->hook.setprocattr(name, value, size); | ||
| 1840 | } | ||
| 1841 | return -EINVAL; | ||
| 1330 | } | 1842 | } |
| 1331 | 1843 | ||
| 1332 | int security_netlink_send(struct sock *sk, struct sk_buff *skb) | 1844 | int security_netlink_send(struct sock *sk, struct sk_buff *skb) |
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index 8af7a690eb40..55f032f1fc2d 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig | |||
| @@ -22,21 +22,6 @@ config SECURITY_SELINUX_BOOTPARAM | |||
| 22 | 22 | ||
| 23 | If you are unsure how to answer this question, answer N. | 23 | If you are unsure how to answer this question, answer N. |
| 24 | 24 | ||
| 25 | config SECURITY_SELINUX_BOOTPARAM_VALUE | ||
| 26 | int "NSA SELinux boot parameter default value" | ||
| 27 | depends on SECURITY_SELINUX_BOOTPARAM | ||
| 28 | range 0 1 | ||
| 29 | default 1 | ||
| 30 | help | ||
| 31 | This option sets the default value for the kernel parameter | ||
| 32 | 'selinux', which allows SELinux to be disabled at boot. If this | ||
| 33 | option is set to 0 (zero), the SELinux kernel parameter will | ||
| 34 | default to 0, disabling SELinux at bootup. If this option is | ||
| 35 | set to 1 (one), the SELinux kernel parameter will default to 1, | ||
| 36 | enabling SELinux at bootup. | ||
| 37 | |||
| 38 | If you are unsure how to answer this question, answer 1. | ||
| 39 | |||
| 40 | config SECURITY_SELINUX_DISABLE | 25 | config SECURITY_SELINUX_DISABLE |
| 41 | bool "NSA SELinux runtime disable" | 26 | bool "NSA SELinux runtime disable" |
| 42 | depends on SECURITY_SELINUX | 27 | depends on SECURITY_SELINUX |
diff --git a/security/selinux/Makefile b/security/selinux/Makefile index c7161f8792b2..ccf950409384 100644 --- a/security/selinux/Makefile +++ b/security/selinux/Makefile | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | obj-$(CONFIG_SECURITY_SELINUX) := selinux.o | 6 | obj-$(CONFIG_SECURITY_SELINUX) := selinux.o |
| 7 | 7 | ||
| 8 | selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o \ | 8 | selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o \ |
| 9 | netnode.o netport.o ibpkey.o exports.o \ | 9 | netnode.o netport.o ibpkey.o \ |
| 10 | ss/ebitmap.o ss/hashtab.o ss/symtab.o ss/sidtab.o ss/avtab.o \ | 10 | ss/ebitmap.o ss/hashtab.o ss/symtab.o ss/sidtab.o ss/avtab.o \ |
| 11 | ss/policydb.o ss/services.o ss/conditional.o ss/mls.o ss/status.o | 11 | ss/policydb.o ss/services.o ss/conditional.o ss/mls.o ss/status.o |
| 12 | 12 | ||
diff --git a/security/selinux/exports.c b/security/selinux/exports.c deleted file mode 100644 index e75dd94e2d2b..000000000000 --- a/security/selinux/exports.c +++ /dev/null | |||
| @@ -1,23 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * SELinux services exported to the rest of the kernel. | ||
| 3 | * | ||
| 4 | * Author: James Morris <jmorris@redhat.com> | ||
| 5 | * | ||
| 6 | * Copyright (C) 2005 Red Hat, Inc., James Morris <jmorris@redhat.com> | ||
| 7 | * Copyright (C) 2006 Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> | ||
| 8 | * Copyright (C) 2006 IBM Corporation, Timothy R. Chavez <tinytim@us.ibm.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2, | ||
| 12 | * as published by the Free Software Foundation. | ||
| 13 | */ | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/selinux.h> | ||
| 16 | |||
| 17 | #include "security.h" | ||
| 18 | |||
| 19 | bool selinux_is_enabled(void) | ||
| 20 | { | ||
| 21 | return selinux_enabled; | ||
| 22 | } | ||
| 23 | EXPORT_SYMBOL_GPL(selinux_is_enabled); | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index f0e36c3492ba..5d92167dbe05 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -79,7 +79,6 @@ | |||
| 79 | #include <linux/personality.h> | 79 | #include <linux/personality.h> |
| 80 | #include <linux/audit.h> | 80 | #include <linux/audit.h> |
| 81 | #include <linux/string.h> | 81 | #include <linux/string.h> |
| 82 | #include <linux/selinux.h> | ||
| 83 | #include <linux/mutex.h> | 82 | #include <linux/mutex.h> |
| 84 | #include <linux/posix-timers.h> | 83 | #include <linux/posix-timers.h> |
| 85 | #include <linux/syslog.h> | 84 | #include <linux/syslog.h> |
| @@ -121,9 +120,8 @@ __setup("enforcing=", enforcing_setup); | |||
| 121 | #define selinux_enforcing_boot 1 | 120 | #define selinux_enforcing_boot 1 |
| 122 | #endif | 121 | #endif |
| 123 | 122 | ||
| 123 | int selinux_enabled __lsm_ro_after_init = 1; | ||
| 124 | #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM | 124 | #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM |
| 125 | int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE; | ||
| 126 | |||
| 127 | static int __init selinux_enabled_setup(char *str) | 125 | static int __init selinux_enabled_setup(char *str) |
| 128 | { | 126 | { |
| 129 | unsigned long enabled; | 127 | unsigned long enabled; |
| @@ -132,8 +130,6 @@ static int __init selinux_enabled_setup(char *str) | |||
| 132 | return 1; | 130 | return 1; |
| 133 | } | 131 | } |
| 134 | __setup("selinux=", selinux_enabled_setup); | 132 | __setup("selinux=", selinux_enabled_setup); |
| 135 | #else | ||
| 136 | int selinux_enabled = 1; | ||
| 137 | #endif | 133 | #endif |
| 138 | 134 | ||
| 139 | static unsigned int selinux_checkreqprot_boot = | 135 | static unsigned int selinux_checkreqprot_boot = |
| @@ -149,9 +145,6 @@ static int __init checkreqprot_setup(char *str) | |||
| 149 | } | 145 | } |
| 150 | __setup("checkreqprot=", checkreqprot_setup); | 146 | __setup("checkreqprot=", checkreqprot_setup); |
| 151 | 147 | ||
| 152 | static struct kmem_cache *sel_inode_cache; | ||
| 153 | static struct kmem_cache *file_security_cache; | ||
| 154 | |||
| 155 | /** | 148 | /** |
| 156 | * selinux_secmark_enabled - Check to see if SECMARK is currently enabled | 149 | * selinux_secmark_enabled - Check to see if SECMARK is currently enabled |
| 157 | * | 150 | * |
| @@ -214,12 +207,8 @@ static void cred_init_security(void) | |||
| 214 | struct cred *cred = (struct cred *) current->real_cred; | 207 | struct cred *cred = (struct cred *) current->real_cred; |
| 215 | struct task_security_struct *tsec; | 208 | struct task_security_struct *tsec; |
| 216 | 209 | ||
| 217 | tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL); | 210 | tsec = selinux_cred(cred); |
| 218 | if (!tsec) | ||
| 219 | panic("SELinux: Failed to initialize initial task.\n"); | ||
| 220 | |||
| 221 | tsec->osid = tsec->sid = SECINITSID_KERNEL; | 211 | tsec->osid = tsec->sid = SECINITSID_KERNEL; |
| 222 | cred->security = tsec; | ||
| 223 | } | 212 | } |
| 224 | 213 | ||
| 225 | /* | 214 | /* |
| @@ -229,7 +218,7 @@ static inline u32 cred_sid(const struct cred *cred) | |||
| 229 | { | 218 | { |
| 230 | const struct task_security_struct *tsec; | 219 | const struct task_security_struct *tsec; |
| 231 | 220 | ||
| 232 | tsec = cred->security; | 221 | tsec = selinux_cred(cred); |
| 233 | return tsec->sid; | 222 | return tsec->sid; |
| 234 | } | 223 | } |
| 235 | 224 | ||
| @@ -250,13 +239,9 @@ static inline u32 task_sid(const struct task_struct *task) | |||
| 250 | 239 | ||
| 251 | static int inode_alloc_security(struct inode *inode) | 240 | static int inode_alloc_security(struct inode *inode) |
| 252 | { | 241 | { |
| 253 | struct inode_security_struct *isec; | 242 | struct inode_security_struct *isec = selinux_inode(inode); |
| 254 | u32 sid = current_sid(); | 243 | u32 sid = current_sid(); |
| 255 | 244 | ||
| 256 | isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS); | ||
| 257 | if (!isec) | ||
| 258 | return -ENOMEM; | ||
| 259 | |||
| 260 | spin_lock_init(&isec->lock); | 245 | spin_lock_init(&isec->lock); |
| 261 | INIT_LIST_HEAD(&isec->list); | 246 | INIT_LIST_HEAD(&isec->list); |
| 262 | isec->inode = inode; | 247 | isec->inode = inode; |
| @@ -264,7 +249,6 @@ static int inode_alloc_security(struct inode *inode) | |||
| 264 | isec->sclass = SECCLASS_FILE; | 249 | isec->sclass = SECCLASS_FILE; |
| 265 | isec->task_sid = sid; | 250 | isec->task_sid = sid; |
| 266 | isec->initialized = LABEL_INVALID; | 251 | isec->initialized = LABEL_INVALID; |
| 267 | inode->i_security = isec; | ||
| 268 | 252 | ||
| 269 | return 0; | 253 | return 0; |
| 270 | } | 254 | } |
| @@ -281,7 +265,7 @@ static int __inode_security_revalidate(struct inode *inode, | |||
| 281 | struct dentry *dentry, | 265 | struct dentry *dentry, |
| 282 | bool may_sleep) | 266 | bool may_sleep) |
| 283 | { | 267 | { |
| 284 | struct inode_security_struct *isec = inode->i_security; | 268 | struct inode_security_struct *isec = selinux_inode(inode); |
| 285 | 269 | ||
| 286 | might_sleep_if(may_sleep); | 270 | might_sleep_if(may_sleep); |
| 287 | 271 | ||
| @@ -302,7 +286,7 @@ static int __inode_security_revalidate(struct inode *inode, | |||
| 302 | 286 | ||
| 303 | static struct inode_security_struct *inode_security_novalidate(struct inode *inode) | 287 | static struct inode_security_struct *inode_security_novalidate(struct inode *inode) |
| 304 | { | 288 | { |
| 305 | return inode->i_security; | 289 | return selinux_inode(inode); |
| 306 | } | 290 | } |
| 307 | 291 | ||
| 308 | static struct inode_security_struct *inode_security_rcu(struct inode *inode, bool rcu) | 292 | static struct inode_security_struct *inode_security_rcu(struct inode *inode, bool rcu) |
| @@ -312,7 +296,7 @@ static struct inode_security_struct *inode_security_rcu(struct inode *inode, boo | |||
| 312 | error = __inode_security_revalidate(inode, NULL, !rcu); | 296 | error = __inode_security_revalidate(inode, NULL, !rcu); |
| 313 | if (error) | 297 | if (error) |
| 314 | return ERR_PTR(error); | 298 | return ERR_PTR(error); |
| 315 | return inode->i_security; | 299 | return selinux_inode(inode); |
| 316 | } | 300 | } |
| 317 | 301 | ||
| 318 | /* | 302 | /* |
| @@ -321,14 +305,14 @@ static struct inode_security_struct *inode_security_rcu(struct inode *inode, boo | |||
| 321 | static struct inode_security_struct *inode_security(struct inode *inode) | 305 | static struct inode_security_struct *inode_security(struct inode *inode) |
| 322 | { | 306 | { |
| 323 | __inode_security_revalidate(inode, NULL, true); | 307 | __inode_security_revalidate(inode, NULL, true); |
| 324 | return inode->i_security; | 308 | return selinux_inode(inode); |
| 325 | } | 309 | } |
| 326 | 310 | ||
| 327 | static struct inode_security_struct *backing_inode_security_novalidate(struct dentry *dentry) | 311 | static struct inode_security_struct *backing_inode_security_novalidate(struct dentry *dentry) |
| 328 | { | 312 | { |
| 329 | struct inode *inode = d_backing_inode(dentry); | 313 | struct inode *inode = d_backing_inode(dentry); |
| 330 | 314 | ||
| 331 | return inode->i_security; | 315 | return selinux_inode(inode); |
| 332 | } | 316 | } |
| 333 | 317 | ||
| 334 | /* | 318 | /* |
| @@ -339,22 +323,17 @@ static struct inode_security_struct *backing_inode_security(struct dentry *dentr | |||
| 339 | struct inode *inode = d_backing_inode(dentry); | 323 | struct inode *inode = d_backing_inode(dentry); |
| 340 | 324 | ||
| 341 | __inode_security_revalidate(inode, dentry, true); | 325 | __inode_security_revalidate(inode, dentry, true); |
| 342 | return inode->i_security; | 326 | return selinux_inode(inode); |
| 343 | } | ||
| 344 | |||
| 345 | static void inode_free_rcu(struct rcu_head *head) | ||
| 346 | { | ||
| 347 | struct inode_security_struct *isec; | ||
| 348 | |||
| 349 | isec = container_of(head, struct inode_security_struct, rcu); | ||
| 350 | kmem_cache_free(sel_inode_cache, isec); | ||
| 351 | } | 327 | } |
| 352 | 328 | ||
| 353 | static void inode_free_security(struct inode *inode) | 329 | static void inode_free_security(struct inode *inode) |
| 354 | { | 330 | { |
| 355 | struct inode_security_struct *isec = inode->i_security; | 331 | struct inode_security_struct *isec = selinux_inode(inode); |
| 356 | struct superblock_security_struct *sbsec = inode->i_sb->s_security; | 332 | struct superblock_security_struct *sbsec; |
| 357 | 333 | ||
| 334 | if (!isec) | ||
| 335 | return; | ||
| 336 | sbsec = inode->i_sb->s_security; | ||
| 358 | /* | 337 | /* |
| 359 | * As not all inode security structures are in a list, we check for | 338 | * As not all inode security structures are in a list, we check for |
| 360 | * empty list outside of the lock to make sure that we won't waste | 339 | * empty list outside of the lock to make sure that we won't waste |
| @@ -370,42 +349,19 @@ static void inode_free_security(struct inode *inode) | |||
| 370 | list_del_init(&isec->list); | 349 | list_del_init(&isec->list); |
| 371 | spin_unlock(&sbsec->isec_lock); | 350 | spin_unlock(&sbsec->isec_lock); |
| 372 | } | 351 | } |
| 373 | |||
| 374 | /* | ||
| 375 | * The inode may still be referenced in a path walk and | ||
| 376 | * a call to selinux_inode_permission() can be made | ||
| 377 | * after inode_free_security() is called. Ideally, the VFS | ||
| 378 | * wouldn't do this, but fixing that is a much harder | ||
| 379 | * job. For now, simply free the i_security via RCU, and | ||
| 380 | * leave the current inode->i_security pointer intact. | ||
| 381 | * The inode will be freed after the RCU grace period too. | ||
| 382 | */ | ||
| 383 | call_rcu(&isec->rcu, inode_free_rcu); | ||
| 384 | } | 352 | } |
| 385 | 353 | ||
| 386 | static int file_alloc_security(struct file *file) | 354 | static int file_alloc_security(struct file *file) |
| 387 | { | 355 | { |
| 388 | struct file_security_struct *fsec; | 356 | struct file_security_struct *fsec = selinux_file(file); |
| 389 | u32 sid = current_sid(); | 357 | u32 sid = current_sid(); |
| 390 | 358 | ||
| 391 | fsec = kmem_cache_zalloc(file_security_cache, GFP_KERNEL); | ||
| 392 | if (!fsec) | ||
| 393 | return -ENOMEM; | ||
| 394 | |||
| 395 | fsec->sid = sid; | 359 | fsec->sid = sid; |
| 396 | fsec->fown_sid = sid; | 360 | fsec->fown_sid = sid; |
| 397 | file->f_security = fsec; | ||
| 398 | 361 | ||
| 399 | return 0; | 362 | return 0; |
| 400 | } | 363 | } |
| 401 | 364 | ||
| 402 | static void file_free_security(struct file *file) | ||
| 403 | { | ||
| 404 | struct file_security_struct *fsec = file->f_security; | ||
| 405 | file->f_security = NULL; | ||
| 406 | kmem_cache_free(file_security_cache, fsec); | ||
| 407 | } | ||
| 408 | |||
| 409 | static int superblock_alloc_security(struct super_block *sb) | 365 | static int superblock_alloc_security(struct super_block *sb) |
| 410 | { | 366 | { |
| 411 | struct superblock_security_struct *sbsec; | 367 | struct superblock_security_struct *sbsec; |
| @@ -501,7 +457,7 @@ static int may_context_mount_sb_relabel(u32 sid, | |||
| 501 | struct superblock_security_struct *sbsec, | 457 | struct superblock_security_struct *sbsec, |
| 502 | const struct cred *cred) | 458 | const struct cred *cred) |
| 503 | { | 459 | { |
| 504 | const struct task_security_struct *tsec = cred->security; | 460 | const struct task_security_struct *tsec = selinux_cred(cred); |
| 505 | int rc; | 461 | int rc; |
| 506 | 462 | ||
| 507 | rc = avc_has_perm(&selinux_state, | 463 | rc = avc_has_perm(&selinux_state, |
| @@ -520,7 +476,7 @@ static int may_context_mount_inode_relabel(u32 sid, | |||
| 520 | struct superblock_security_struct *sbsec, | 476 | struct superblock_security_struct *sbsec, |
| 521 | const struct cred *cred) | 477 | const struct cred *cred) |
| 522 | { | 478 | { |
| 523 | const struct task_security_struct *tsec = cred->security; | 479 | const struct task_security_struct *tsec = selinux_cred(cred); |
| 524 | int rc; | 480 | int rc; |
| 525 | rc = avc_has_perm(&selinux_state, | 481 | rc = avc_has_perm(&selinux_state, |
| 526 | tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, | 482 | tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, |
| @@ -1374,7 +1330,7 @@ static int selinux_genfs_get_sid(struct dentry *dentry, | |||
| 1374 | static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry) | 1330 | static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry) |
| 1375 | { | 1331 | { |
| 1376 | struct superblock_security_struct *sbsec = NULL; | 1332 | struct superblock_security_struct *sbsec = NULL; |
| 1377 | struct inode_security_struct *isec = inode->i_security; | 1333 | struct inode_security_struct *isec = selinux_inode(inode); |
| 1378 | u32 task_sid, sid = 0; | 1334 | u32 task_sid, sid = 0; |
| 1379 | u16 sclass; | 1335 | u16 sclass; |
| 1380 | struct dentry *dentry; | 1336 | struct dentry *dentry; |
| @@ -1621,7 +1577,7 @@ static inline u32 signal_to_av(int sig) | |||
| 1621 | 1577 | ||
| 1622 | /* Check whether a task is allowed to use a capability. */ | 1578 | /* Check whether a task is allowed to use a capability. */ |
| 1623 | static int cred_has_capability(const struct cred *cred, | 1579 | static int cred_has_capability(const struct cred *cred, |
| 1624 | int cap, int audit, bool initns) | 1580 | int cap, unsigned int opts, bool initns) |
| 1625 | { | 1581 | { |
| 1626 | struct common_audit_data ad; | 1582 | struct common_audit_data ad; |
| 1627 | struct av_decision avd; | 1583 | struct av_decision avd; |
| @@ -1648,7 +1604,7 @@ static int cred_has_capability(const struct cred *cred, | |||
| 1648 | 1604 | ||
| 1649 | rc = avc_has_perm_noaudit(&selinux_state, | 1605 | rc = avc_has_perm_noaudit(&selinux_state, |
| 1650 | sid, sid, sclass, av, 0, &avd); | 1606 | sid, sid, sclass, av, 0, &avd); |
| 1651 | if (audit == SECURITY_CAP_AUDIT) { | 1607 | if (!(opts & CAP_OPT_NOAUDIT)) { |
| 1652 | int rc2 = avc_audit(&selinux_state, | 1608 | int rc2 = avc_audit(&selinux_state, |
| 1653 | sid, sid, sclass, av, &avd, rc, &ad, 0); | 1609 | sid, sid, sclass, av, &avd, rc, &ad, 0); |
| 1654 | if (rc2) | 1610 | if (rc2) |
| @@ -1674,7 +1630,7 @@ static int inode_has_perm(const struct cred *cred, | |||
| 1674 | return 0; | 1630 | return 0; |
| 1675 | 1631 | ||
| 1676 | sid = cred_sid(cred); | 1632 | sid = cred_sid(cred); |
| 1677 | isec = inode->i_security; | 1633 | isec = selinux_inode(inode); |
| 1678 | 1634 | ||
| 1679 | return avc_has_perm(&selinux_state, | 1635 | return avc_has_perm(&selinux_state, |
| 1680 | sid, isec->sid, isec->sclass, perms, adp); | 1636 | sid, isec->sid, isec->sclass, perms, adp); |
| @@ -1740,7 +1696,7 @@ static int file_has_perm(const struct cred *cred, | |||
| 1740 | struct file *file, | 1696 | struct file *file, |
| 1741 | u32 av) | 1697 | u32 av) |
| 1742 | { | 1698 | { |
| 1743 | struct file_security_struct *fsec = file->f_security; | 1699 | struct file_security_struct *fsec = selinux_file(file); |
| 1744 | struct inode *inode = file_inode(file); | 1700 | struct inode *inode = file_inode(file); |
| 1745 | struct common_audit_data ad; | 1701 | struct common_audit_data ad; |
| 1746 | u32 sid = cred_sid(cred); | 1702 | u32 sid = cred_sid(cred); |
| @@ -1806,7 +1762,7 @@ static int may_create(struct inode *dir, | |||
| 1806 | struct dentry *dentry, | 1762 | struct dentry *dentry, |
| 1807 | u16 tclass) | 1763 | u16 tclass) |
| 1808 | { | 1764 | { |
| 1809 | const struct task_security_struct *tsec = current_security(); | 1765 | const struct task_security_struct *tsec = selinux_cred(current_cred()); |
| 1810 | struct inode_security_struct *dsec; | 1766 | struct inode_security_struct *dsec; |
| 1811 | struct superblock_security_struct *sbsec; | 1767 | struct superblock_security_struct *sbsec; |
| 1812 | u32 sid, newsid; | 1768 | u32 sid, newsid; |
| @@ -1828,7 +1784,7 @@ static int may_create(struct inode *dir, | |||
| 1828 | if (rc) | 1784 | if (rc) |
| 1829 | return rc; | 1785 | return rc; |
| 1830 | 1786 | ||
| 1831 | rc = selinux_determine_inode_label(current_security(), dir, | 1787 | rc = selinux_determine_inode_label(selinux_cred(current_cred()), dir, |
| 1832 | &dentry->d_name, tclass, &newsid); | 1788 | &dentry->d_name, tclass, &newsid); |
| 1833 | if (rc) | 1789 | if (rc) |
| 1834 | return rc; | 1790 | return rc; |
| @@ -2084,7 +2040,7 @@ static int selinux_binder_transfer_file(struct task_struct *from, | |||
| 2084 | struct file *file) | 2040 | struct file *file) |
| 2085 | { | 2041 | { |
| 2086 | u32 sid = task_sid(to); | 2042 | u32 sid = task_sid(to); |
| 2087 | struct file_security_struct *fsec = file->f_security; | 2043 | struct file_security_struct *fsec = selinux_file(file); |
| 2088 | struct dentry *dentry = file->f_path.dentry; | 2044 | struct dentry *dentry = file->f_path.dentry; |
| 2089 | struct inode_security_struct *isec; | 2045 | struct inode_security_struct *isec; |
| 2090 | struct common_audit_data ad; | 2046 | struct common_audit_data ad; |
| @@ -2168,9 +2124,9 @@ static int selinux_capset(struct cred *new, const struct cred *old, | |||
| 2168 | */ | 2124 | */ |
| 2169 | 2125 | ||
| 2170 | static int selinux_capable(const struct cred *cred, struct user_namespace *ns, | 2126 | static int selinux_capable(const struct cred *cred, struct user_namespace *ns, |
| 2171 | int cap, int audit) | 2127 | int cap, unsigned int opts) |
| 2172 | { | 2128 | { |
| 2173 | return cred_has_capability(cred, cap, audit, ns == &init_user_ns); | 2129 | return cred_has_capability(cred, cap, opts, ns == &init_user_ns); |
| 2174 | } | 2130 | } |
| 2175 | 2131 | ||
| 2176 | static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb) | 2132 | static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb) |
| @@ -2244,7 +2200,7 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) | |||
| 2244 | int rc, cap_sys_admin = 0; | 2200 | int rc, cap_sys_admin = 0; |
| 2245 | 2201 | ||
| 2246 | rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN, | 2202 | rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN, |
| 2247 | SECURITY_CAP_NOAUDIT, true); | 2203 | CAP_OPT_NOAUDIT, true); |
| 2248 | if (rc == 0) | 2204 | if (rc == 0) |
| 2249 | cap_sys_admin = 1; | 2205 | cap_sys_admin = 1; |
| 2250 | 2206 | ||
| @@ -2335,8 +2291,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
| 2335 | if (bprm->called_set_creds) | 2291 | if (bprm->called_set_creds) |
| 2336 | return 0; | 2292 | return 0; |
| 2337 | 2293 | ||
| 2338 | old_tsec = current_security(); | 2294 | old_tsec = selinux_cred(current_cred()); |
| 2339 | new_tsec = bprm->cred->security; | 2295 | new_tsec = selinux_cred(bprm->cred); |
| 2340 | isec = inode_security(inode); | 2296 | isec = inode_security(inode); |
| 2341 | 2297 | ||
| 2342 | /* Default to the current task SID. */ | 2298 | /* Default to the current task SID. */ |
| @@ -2500,7 +2456,7 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm) | |||
| 2500 | struct rlimit *rlim, *initrlim; | 2456 | struct rlimit *rlim, *initrlim; |
| 2501 | int rc, i; | 2457 | int rc, i; |
| 2502 | 2458 | ||
| 2503 | new_tsec = bprm->cred->security; | 2459 | new_tsec = selinux_cred(bprm->cred); |
| 2504 | if (new_tsec->sid == new_tsec->osid) | 2460 | if (new_tsec->sid == new_tsec->osid) |
| 2505 | return; | 2461 | return; |
| 2506 | 2462 | ||
| @@ -2543,7 +2499,7 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm) | |||
| 2543 | */ | 2499 | */ |
| 2544 | static void selinux_bprm_committed_creds(struct linux_binprm *bprm) | 2500 | static void selinux_bprm_committed_creds(struct linux_binprm *bprm) |
| 2545 | { | 2501 | { |
| 2546 | const struct task_security_struct *tsec = current_security(); | 2502 | const struct task_security_struct *tsec = selinux_cred(current_cred()); |
| 2547 | struct itimerval itimer; | 2503 | struct itimerval itimer; |
| 2548 | u32 osid, sid; | 2504 | u32 osid, sid; |
| 2549 | int rc, i; | 2505 | int rc, i; |
| @@ -2780,7 +2736,7 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode, | |||
| 2780 | u32 newsid; | 2736 | u32 newsid; |
| 2781 | int rc; | 2737 | int rc; |
| 2782 | 2738 | ||
| 2783 | rc = selinux_determine_inode_label(current_security(), | 2739 | rc = selinux_determine_inode_label(selinux_cred(current_cred()), |
| 2784 | d_inode(dentry->d_parent), name, | 2740 | d_inode(dentry->d_parent), name, |
| 2785 | inode_mode_to_security_class(mode), | 2741 | inode_mode_to_security_class(mode), |
| 2786 | &newsid); | 2742 | &newsid); |
| @@ -2800,14 +2756,14 @@ static int selinux_dentry_create_files_as(struct dentry *dentry, int mode, | |||
| 2800 | int rc; | 2756 | int rc; |
| 2801 | struct task_security_struct *tsec; | 2757 | struct task_security_struct *tsec; |
| 2802 | 2758 | ||
| 2803 | rc = selinux_determine_inode_label(old->security, | 2759 | rc = selinux_determine_inode_label(selinux_cred(old), |
| 2804 | d_inode(dentry->d_parent), name, | 2760 | d_inode(dentry->d_parent), name, |
| 2805 | inode_mode_to_security_class(mode), | 2761 | inode_mode_to_security_class(mode), |
| 2806 | &newsid); | 2762 | &newsid); |
| 2807 | if (rc) | 2763 | if (rc) |
| 2808 | return rc; | 2764 | return rc; |
| 2809 | 2765 | ||
| 2810 | tsec = new->security; | 2766 | tsec = selinux_cred(new); |
| 2811 | tsec->create_sid = newsid; | 2767 | tsec->create_sid = newsid; |
| 2812 | return 0; | 2768 | return 0; |
| 2813 | } | 2769 | } |
| @@ -2817,7 +2773,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
| 2817 | const char **name, | 2773 | const char **name, |
| 2818 | void **value, size_t *len) | 2774 | void **value, size_t *len) |
| 2819 | { | 2775 | { |
| 2820 | const struct task_security_struct *tsec = current_security(); | 2776 | const struct task_security_struct *tsec = selinux_cred(current_cred()); |
| 2821 | struct superblock_security_struct *sbsec; | 2777 | struct superblock_security_struct *sbsec; |
| 2822 | u32 newsid, clen; | 2778 | u32 newsid, clen; |
| 2823 | int rc; | 2779 | int rc; |
| @@ -2827,7 +2783,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
| 2827 | 2783 | ||
| 2828 | newsid = tsec->create_sid; | 2784 | newsid = tsec->create_sid; |
| 2829 | 2785 | ||
| 2830 | rc = selinux_determine_inode_label(current_security(), | 2786 | rc = selinux_determine_inode_label(selinux_cred(current_cred()), |
| 2831 | dir, qstr, | 2787 | dir, qstr, |
| 2832 | inode_mode_to_security_class(inode->i_mode), | 2788 | inode_mode_to_security_class(inode->i_mode), |
| 2833 | &newsid); | 2789 | &newsid); |
| @@ -2836,7 +2792,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
| 2836 | 2792 | ||
| 2837 | /* Possibly defer initialization to selinux_complete_init. */ | 2793 | /* Possibly defer initialization to selinux_complete_init. */ |
| 2838 | if (sbsec->flags & SE_SBINITIALIZED) { | 2794 | if (sbsec->flags & SE_SBINITIALIZED) { |
| 2839 | struct inode_security_struct *isec = inode->i_security; | 2795 | struct inode_security_struct *isec = selinux_inode(inode); |
| 2840 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | 2796 | isec->sclass = inode_mode_to_security_class(inode->i_mode); |
| 2841 | isec->sid = newsid; | 2797 | isec->sid = newsid; |
| 2842 | isec->initialized = LABEL_INITIALIZED; | 2798 | isec->initialized = LABEL_INITIALIZED; |
| @@ -2936,7 +2892,7 @@ static noinline int audit_inode_permission(struct inode *inode, | |||
| 2936 | unsigned flags) | 2892 | unsigned flags) |
| 2937 | { | 2893 | { |
| 2938 | struct common_audit_data ad; | 2894 | struct common_audit_data ad; |
| 2939 | struct inode_security_struct *isec = inode->i_security; | 2895 | struct inode_security_struct *isec = selinux_inode(inode); |
| 2940 | int rc; | 2896 | int rc; |
| 2941 | 2897 | ||
| 2942 | ad.type = LSM_AUDIT_DATA_INODE; | 2898 | ad.type = LSM_AUDIT_DATA_INODE; |
| @@ -3031,11 +2987,11 @@ static int selinux_inode_getattr(const struct path *path) | |||
| 3031 | static bool has_cap_mac_admin(bool audit) | 2987 | static bool has_cap_mac_admin(bool audit) |
| 3032 | { | 2988 | { |
| 3033 | const struct cred *cred = current_cred(); | 2989 | const struct cred *cred = current_cred(); |
| 3034 | int cap_audit = audit ? SECURITY_CAP_AUDIT : SECURITY_CAP_NOAUDIT; | 2990 | unsigned int opts = audit ? CAP_OPT_NONE : CAP_OPT_NOAUDIT; |
| 3035 | 2991 | ||
| 3036 | if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, cap_audit)) | 2992 | if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, opts)) |
| 3037 | return false; | 2993 | return false; |
| 3038 | if (cred_has_capability(cred, CAP_MAC_ADMIN, cap_audit, true)) | 2994 | if (cred_has_capability(cred, CAP_MAC_ADMIN, opts, true)) |
| 3039 | return false; | 2995 | return false; |
| 3040 | return true; | 2996 | return true; |
| 3041 | } | 2997 | } |
| @@ -3289,7 +3245,7 @@ static int selinux_inode_copy_up(struct dentry *src, struct cred **new) | |||
| 3289 | return -ENOMEM; | 3245 | return -ENOMEM; |
| 3290 | } | 3246 | } |
| 3291 | 3247 | ||
| 3292 | tsec = new_creds->security; | 3248 | tsec = selinux_cred(new_creds); |
| 3293 | /* Get label from overlay inode and set it in create_sid */ | 3249 | /* Get label from overlay inode and set it in create_sid */ |
| 3294 | selinux_inode_getsecid(d_inode(src), &sid); | 3250 | selinux_inode_getsecid(d_inode(src), &sid); |
| 3295 | tsec->create_sid = sid; | 3251 | tsec->create_sid = sid; |
| @@ -3330,7 +3286,7 @@ static int selinux_revalidate_file_permission(struct file *file, int mask) | |||
| 3330 | static int selinux_file_permission(struct file *file, int mask) | 3286 | static int selinux_file_permission(struct file *file, int mask) |
| 3331 | { | 3287 | { |
| 3332 | struct inode *inode = file_inode(file); | 3288 | struct inode *inode = file_inode(file); |
| 3333 | struct file_security_struct *fsec = file->f_security; | 3289 | struct file_security_struct *fsec = selinux_file(file); |
| 3334 | struct inode_security_struct *isec; | 3290 | struct inode_security_struct *isec; |
| 3335 | u32 sid = current_sid(); | 3291 | u32 sid = current_sid(); |
| 3336 | 3292 | ||
| @@ -3352,11 +3308,6 @@ static int selinux_file_alloc_security(struct file *file) | |||
| 3352 | return file_alloc_security(file); | 3308 | return file_alloc_security(file); |
| 3353 | } | 3309 | } |
| 3354 | 3310 | ||
| 3355 | static void selinux_file_free_security(struct file *file) | ||
| 3356 | { | ||
| 3357 | file_free_security(file); | ||
| 3358 | } | ||
| 3359 | |||
| 3360 | /* | 3311 | /* |
| 3361 | * Check whether a task has the ioctl permission and cmd | 3312 | * Check whether a task has the ioctl permission and cmd |
| 3362 | * operation to an inode. | 3313 | * operation to an inode. |
| @@ -3365,7 +3316,7 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file, | |||
| 3365 | u32 requested, u16 cmd) | 3316 | u32 requested, u16 cmd) |
| 3366 | { | 3317 | { |
| 3367 | struct common_audit_data ad; | 3318 | struct common_audit_data ad; |
| 3368 | struct file_security_struct *fsec = file->f_security; | 3319 | struct file_security_struct *fsec = selinux_file(file); |
| 3369 | struct inode *inode = file_inode(file); | 3320 | struct inode *inode = file_inode(file); |
| 3370 | struct inode_security_struct *isec; | 3321 | struct inode_security_struct *isec; |
| 3371 | struct lsm_ioctlop_audit ioctl; | 3322 | struct lsm_ioctlop_audit ioctl; |
| @@ -3435,7 +3386,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, | |||
| 3435 | case KDSKBENT: | 3386 | case KDSKBENT: |
| 3436 | case KDSKBSENT: | 3387 | case KDSKBSENT: |
| 3437 | error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG, | 3388 | error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG, |
| 3438 | SECURITY_CAP_AUDIT, true); | 3389 | CAP_OPT_NONE, true); |
| 3439 | break; | 3390 | break; |
| 3440 | 3391 | ||
| 3441 | /* default case assumes that the command will go | 3392 | /* default case assumes that the command will go |
| @@ -3617,7 +3568,7 @@ static void selinux_file_set_fowner(struct file *file) | |||
| 3617 | { | 3568 | { |
| 3618 | struct file_security_struct *fsec; | 3569 | struct file_security_struct *fsec; |
| 3619 | 3570 | ||
| 3620 | fsec = file->f_security; | 3571 | fsec = selinux_file(file); |
| 3621 | fsec->fown_sid = current_sid(); | 3572 | fsec->fown_sid = current_sid(); |
| 3622 | } | 3573 | } |
| 3623 | 3574 | ||
| @@ -3632,7 +3583,7 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk, | |||
| 3632 | /* struct fown_struct is never outside the context of a struct file */ | 3583 | /* struct fown_struct is never outside the context of a struct file */ |
| 3633 | file = container_of(fown, struct file, f_owner); | 3584 | file = container_of(fown, struct file, f_owner); |
| 3634 | 3585 | ||
| 3635 | fsec = file->f_security; | 3586 | fsec = selinux_file(file); |
| 3636 | 3587 | ||
| 3637 | if (!signum) | 3588 | if (!signum) |
| 3638 | perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */ | 3589 | perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */ |
| @@ -3656,7 +3607,7 @@ static int selinux_file_open(struct file *file) | |||
| 3656 | struct file_security_struct *fsec; | 3607 | struct file_security_struct *fsec; |
| 3657 | struct inode_security_struct *isec; | 3608 | struct inode_security_struct *isec; |
| 3658 | 3609 | ||
| 3659 | fsec = file->f_security; | 3610 | fsec = selinux_file(file); |
| 3660 | isec = inode_security(file_inode(file)); | 3611 | isec = inode_security(file_inode(file)); |
| 3661 | /* | 3612 | /* |
| 3662 | * Save inode label and policy sequence number | 3613 | * Save inode label and policy sequence number |
| @@ -3690,52 +3641,15 @@ static int selinux_task_alloc(struct task_struct *task, | |||
| 3690 | } | 3641 | } |
| 3691 | 3642 | ||
| 3692 | /* | 3643 | /* |
| 3693 | * allocate the SELinux part of blank credentials | ||
| 3694 | */ | ||
| 3695 | static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp) | ||
| 3696 | { | ||
| 3697 | struct task_security_struct *tsec; | ||
| 3698 | |||
| 3699 | tsec = kzalloc(sizeof(struct task_security_struct), gfp); | ||
| 3700 | if (!tsec) | ||
| 3701 | return -ENOMEM; | ||
| 3702 | |||
| 3703 | cred->security = tsec; | ||
| 3704 | return 0; | ||
| 3705 | } | ||
| 3706 | |||
| 3707 | /* | ||
| 3708 | * detach and free the LSM part of a set of credentials | ||
| 3709 | */ | ||
| 3710 | static void selinux_cred_free(struct cred *cred) | ||
| 3711 | { | ||
| 3712 | struct task_security_struct *tsec = cred->security; | ||
| 3713 | |||
| 3714 | /* | ||
| 3715 | * cred->security == NULL if security_cred_alloc_blank() or | ||
| 3716 | * security_prepare_creds() returned an error. | ||
| 3717 | */ | ||
| 3718 | BUG_ON(cred->security && (unsigned long) cred->security < PAGE_SIZE); | ||
| 3719 | cred->security = (void *) 0x7UL; | ||
| 3720 | kfree(tsec); | ||
| 3721 | } | ||
| 3722 | |||
| 3723 | /* | ||
| 3724 | * prepare a new set of credentials for modification | 3644 | * prepare a new set of credentials for modification |
| 3725 | */ | 3645 | */ |
| 3726 | static int selinux_cred_prepare(struct cred *new, const struct cred *old, | 3646 | static int selinux_cred_prepare(struct cred *new, const struct cred *old, |
| 3727 | gfp_t gfp) | 3647 | gfp_t gfp) |
| 3728 | { | 3648 | { |
| 3729 | const struct task_security_struct *old_tsec; | 3649 | const struct task_security_struct *old_tsec = selinux_cred(old); |
| 3730 | struct task_security_struct *tsec; | 3650 | struct task_security_struct *tsec = selinux_cred(new); |
| 3731 | |||
| 3732 | old_tsec = old->security; | ||
| 3733 | 3651 | ||
| 3734 | tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp); | 3652 | *tsec = *old_tsec; |
| 3735 | if (!tsec) | ||
| 3736 | return -ENOMEM; | ||
| 3737 | |||
| 3738 | new->security = tsec; | ||
| 3739 | return 0; | 3653 | return 0; |
| 3740 | } | 3654 | } |
| 3741 | 3655 | ||
| @@ -3744,8 +3658,8 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old, | |||
| 3744 | */ | 3658 | */ |
| 3745 | static void selinux_cred_transfer(struct cred *new, const struct cred *old) | 3659 | static void selinux_cred_transfer(struct cred *new, const struct cred *old) |
| 3746 | { | 3660 | { |
| 3747 | const struct task_security_struct *old_tsec = old->security; | 3661 | const struct task_security_struct *old_tsec = selinux_cred(old); |
| 3748 | struct task_security_struct *tsec = new->security; | 3662 | struct task_security_struct *tsec = selinux_cred(new); |
| 3749 | 3663 | ||
| 3750 | *tsec = *old_tsec; | 3664 | *tsec = *old_tsec; |
| 3751 | } | 3665 | } |
| @@ -3761,7 +3675,7 @@ static void selinux_cred_getsecid(const struct cred *c, u32 *secid) | |||
| 3761 | */ | 3675 | */ |
| 3762 | static int selinux_kernel_act_as(struct cred *new, u32 secid) | 3676 | static int selinux_kernel_act_as(struct cred *new, u32 secid) |
| 3763 | { | 3677 | { |
| 3764 | struct task_security_struct *tsec = new->security; | 3678 | struct task_security_struct *tsec = selinux_cred(new); |
| 3765 | u32 sid = current_sid(); | 3679 | u32 sid = current_sid(); |
| 3766 | int ret; | 3680 | int ret; |
| 3767 | 3681 | ||
| @@ -3786,7 +3700,7 @@ static int selinux_kernel_act_as(struct cred *new, u32 secid) | |||
| 3786 | static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) | 3700 | static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) |
| 3787 | { | 3701 | { |
| 3788 | struct inode_security_struct *isec = inode_security(inode); | 3702 | struct inode_security_struct *isec = inode_security(inode); |
| 3789 | struct task_security_struct *tsec = new->security; | 3703 | struct task_security_struct *tsec = selinux_cred(new); |
| 3790 | u32 sid = current_sid(); | 3704 | u32 sid = current_sid(); |
| 3791 | int ret; | 3705 | int ret; |
| 3792 | 3706 | ||
| @@ -3832,7 +3746,7 @@ static int selinux_kernel_module_from_file(struct file *file) | |||
| 3832 | ad.type = LSM_AUDIT_DATA_FILE; | 3746 | ad.type = LSM_AUDIT_DATA_FILE; |
| 3833 | ad.u.file = file; | 3747 | ad.u.file = file; |
| 3834 | 3748 | ||
| 3835 | fsec = file->f_security; | 3749 | fsec = selinux_file(file); |
| 3836 | if (sid != fsec->sid) { | 3750 | if (sid != fsec->sid) { |
| 3837 | rc = avc_has_perm(&selinux_state, | 3751 | rc = avc_has_perm(&selinux_state, |
| 3838 | sid, fsec->sid, SECCLASS_FD, FD__USE, &ad); | 3752 | sid, fsec->sid, SECCLASS_FD, FD__USE, &ad); |
| @@ -3998,7 +3912,7 @@ static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info, | |||
| 3998 | static void selinux_task_to_inode(struct task_struct *p, | 3912 | static void selinux_task_to_inode(struct task_struct *p, |
| 3999 | struct inode *inode) | 3913 | struct inode *inode) |
| 4000 | { | 3914 | { |
| 4001 | struct inode_security_struct *isec = inode->i_security; | 3915 | struct inode_security_struct *isec = selinux_inode(inode); |
| 4002 | u32 sid = task_sid(p); | 3916 | u32 sid = task_sid(p); |
| 4003 | 3917 | ||
| 4004 | spin_lock(&isec->lock); | 3918 | spin_lock(&isec->lock); |
| @@ -4335,7 +4249,7 @@ static int sock_has_perm(struct sock *sk, u32 perms) | |||
| 4335 | static int selinux_socket_create(int family, int type, | 4249 | static int selinux_socket_create(int family, int type, |
| 4336 | int protocol, int kern) | 4250 | int protocol, int kern) |
| 4337 | { | 4251 | { |
| 4338 | const struct task_security_struct *tsec = current_security(); | 4252 | const struct task_security_struct *tsec = selinux_cred(current_cred()); |
| 4339 | u32 newsid; | 4253 | u32 newsid; |
| 4340 | u16 secclass; | 4254 | u16 secclass; |
| 4341 | int rc; | 4255 | int rc; |
| @@ -4355,7 +4269,7 @@ static int selinux_socket_create(int family, int type, | |||
| 4355 | static int selinux_socket_post_create(struct socket *sock, int family, | 4269 | static int selinux_socket_post_create(struct socket *sock, int family, |
| 4356 | int type, int protocol, int kern) | 4270 | int type, int protocol, int kern) |
| 4357 | { | 4271 | { |
| 4358 | const struct task_security_struct *tsec = current_security(); | 4272 | const struct task_security_struct *tsec = selinux_cred(current_cred()); |
| 4359 | struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock)); | 4273 | struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock)); |
| 4360 | struct sk_security_struct *sksec; | 4274 | struct sk_security_struct *sksec; |
| 4361 | u16 sclass = socket_type_to_security_class(family, type, protocol); | 4275 | u16 sclass = socket_type_to_security_class(family, type, protocol); |
| @@ -5236,7 +5150,7 @@ static int selinux_secmark_relabel_packet(u32 sid) | |||
| 5236 | const struct task_security_struct *__tsec; | 5150 | const struct task_security_struct *__tsec; |
| 5237 | u32 tsid; | 5151 | u32 tsid; |
| 5238 | 5152 | ||
| 5239 | __tsec = current_security(); | 5153 | __tsec = selinux_cred(current_cred()); |
| 5240 | tsid = __tsec->sid; | 5154 | tsid = __tsec->sid; |
| 5241 | 5155 | ||
| 5242 | return avc_has_perm(&selinux_state, | 5156 | return avc_has_perm(&selinux_state, |
| @@ -5711,51 +5625,22 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) | |||
| 5711 | return selinux_nlmsg_perm(sk, skb); | 5625 | return selinux_nlmsg_perm(sk, skb); |
| 5712 | } | 5626 | } |
| 5713 | 5627 | ||
| 5714 | static int ipc_alloc_security(struct kern_ipc_perm *perm, | 5628 | static void ipc_init_security(struct ipc_security_struct *isec, u16 sclass) |
| 5715 | u16 sclass) | ||
| 5716 | { | 5629 | { |
| 5717 | struct ipc_security_struct *isec; | ||
| 5718 | |||
| 5719 | isec = kzalloc(sizeof(struct ipc_security_struct), GFP_KERNEL); | ||
| 5720 | if (!isec) | ||
| 5721 | return -ENOMEM; | ||
| 5722 | |||
| 5723 | isec->sclass = sclass; | 5630 | isec->sclass = sclass; |
| 5724 | isec->sid = current_sid(); | 5631 | isec->sid = current_sid(); |
| 5725 | perm->security = isec; | ||
| 5726 | |||
| 5727 | return 0; | ||
| 5728 | } | ||
| 5729 | |||
| 5730 | static void ipc_free_security(struct kern_ipc_perm *perm) | ||
| 5731 | { | ||
| 5732 | struct ipc_security_struct *isec = perm->security; | ||
| 5733 | perm->security = NULL; | ||
| 5734 | kfree(isec); | ||
| 5735 | } | 5632 | } |
| 5736 | 5633 | ||
| 5737 | static int msg_msg_alloc_security(struct msg_msg *msg) | 5634 | static int msg_msg_alloc_security(struct msg_msg *msg) |
| 5738 | { | 5635 | { |
| 5739 | struct msg_security_struct *msec; | 5636 | struct msg_security_struct *msec; |
| 5740 | 5637 | ||
| 5741 | msec = kzalloc(sizeof(struct msg_security_struct), GFP_KERNEL); | 5638 | msec = selinux_msg_msg(msg); |
| 5742 | if (!msec) | ||
| 5743 | return -ENOMEM; | ||
| 5744 | |||
| 5745 | msec->sid = SECINITSID_UNLABELED; | 5639 | msec->sid = SECINITSID_UNLABELED; |
| 5746 | msg->security = msec; | ||
| 5747 | 5640 | ||
| 5748 | return 0; | 5641 | return 0; |
| 5749 | } | 5642 | } |
| 5750 | 5643 | ||
| 5751 | static void msg_msg_free_security(struct msg_msg *msg) | ||
| 5752 | { | ||
| 5753 | struct msg_security_struct *msec = msg->security; | ||
| 5754 | |||
| 5755 | msg->security = NULL; | ||
| 5756 | kfree(msec); | ||
| 5757 | } | ||
| 5758 | |||
| 5759 | static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, | 5644 | static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, |
| 5760 | u32 perms) | 5645 | u32 perms) |
| 5761 | { | 5646 | { |
| @@ -5763,7 +5648,7 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, | |||
| 5763 | struct common_audit_data ad; | 5648 | struct common_audit_data ad; |
| 5764 | u32 sid = current_sid(); | 5649 | u32 sid = current_sid(); |
| 5765 | 5650 | ||
| 5766 | isec = ipc_perms->security; | 5651 | isec = selinux_ipc(ipc_perms); |
| 5767 | 5652 | ||
| 5768 | ad.type = LSM_AUDIT_DATA_IPC; | 5653 | ad.type = LSM_AUDIT_DATA_IPC; |
| 5769 | ad.u.ipc_id = ipc_perms->key; | 5654 | ad.u.ipc_id = ipc_perms->key; |
| @@ -5777,11 +5662,6 @@ static int selinux_msg_msg_alloc_security(struct msg_msg *msg) | |||
| 5777 | return msg_msg_alloc_security(msg); | 5662 | return msg_msg_alloc_security(msg); |
| 5778 | } | 5663 | } |
| 5779 | 5664 | ||
| 5780 | static void selinux_msg_msg_free_security(struct msg_msg *msg) | ||
| 5781 | { | ||
| 5782 | msg_msg_free_security(msg); | ||
| 5783 | } | ||
| 5784 | |||
| 5785 | /* message queue security operations */ | 5665 | /* message queue security operations */ |
| 5786 | static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq) | 5666 | static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq) |
| 5787 | { | 5667 | { |
| @@ -5790,11 +5670,8 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq) | |||
| 5790 | u32 sid = current_sid(); | 5670 | u32 sid = current_sid(); |
| 5791 | int rc; | 5671 | int rc; |
| 5792 | 5672 | ||
| 5793 | rc = ipc_alloc_security(msq, SECCLASS_MSGQ); | 5673 | isec = selinux_ipc(msq); |
| 5794 | if (rc) | 5674 | ipc_init_security(isec, SECCLASS_MSGQ); |
| 5795 | return rc; | ||
| 5796 | |||
| 5797 | isec = msq->security; | ||
| 5798 | 5675 | ||
| 5799 | ad.type = LSM_AUDIT_DATA_IPC; | 5676 | ad.type = LSM_AUDIT_DATA_IPC; |
| 5800 | ad.u.ipc_id = msq->key; | 5677 | ad.u.ipc_id = msq->key; |
| @@ -5802,16 +5679,7 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq) | |||
| 5802 | rc = avc_has_perm(&selinux_state, | 5679 | rc = avc_has_perm(&selinux_state, |
| 5803 | sid, isec->sid, SECCLASS_MSGQ, | 5680 | sid, isec->sid, SECCLASS_MSGQ, |
| 5804 | MSGQ__CREATE, &ad); | 5681 | MSGQ__CREATE, &ad); |
| 5805 | if (rc) { | 5682 | return rc; |
| 5806 | ipc_free_security(msq); | ||
| 5807 | return rc; | ||
| 5808 | } | ||
| 5809 | return 0; | ||
| 5810 | } | ||
| 5811 | |||
| 5812 | static void selinux_msg_queue_free_security(struct kern_ipc_perm *msq) | ||
| 5813 | { | ||
| 5814 | ipc_free_security(msq); | ||
| 5815 | } | 5683 | } |
| 5816 | 5684 | ||
| 5817 | static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) | 5685 | static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) |
| @@ -5820,7 +5688,7 @@ static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) | |||
| 5820 | struct common_audit_data ad; | 5688 | struct common_audit_data ad; |
| 5821 | u32 sid = current_sid(); | 5689 | u32 sid = current_sid(); |
| 5822 | 5690 | ||
| 5823 | isec = msq->security; | 5691 | isec = selinux_ipc(msq); |
| 5824 | 5692 | ||
| 5825 | ad.type = LSM_AUDIT_DATA_IPC; | 5693 | ad.type = LSM_AUDIT_DATA_IPC; |
| 5826 | ad.u.ipc_id = msq->key; | 5694 | ad.u.ipc_id = msq->key; |
| @@ -5869,8 +5737,8 @@ static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *m | |||
| 5869 | u32 sid = current_sid(); | 5737 | u32 sid = current_sid(); |
| 5870 | int rc; | 5738 | int rc; |
| 5871 | 5739 | ||
| 5872 | isec = msq->security; | 5740 | isec = selinux_ipc(msq); |
| 5873 | msec = msg->security; | 5741 | msec = selinux_msg_msg(msg); |
| 5874 | 5742 | ||
| 5875 | /* | 5743 | /* |
| 5876 | * First time through, need to assign label to the message | 5744 | * First time through, need to assign label to the message |
| @@ -5917,8 +5785,8 @@ static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *m | |||
| 5917 | u32 sid = task_sid(target); | 5785 | u32 sid = task_sid(target); |
| 5918 | int rc; | 5786 | int rc; |
| 5919 | 5787 | ||
| 5920 | isec = msq->security; | 5788 | isec = selinux_ipc(msq); |
| 5921 | msec = msg->security; | 5789 | msec = selinux_msg_msg(msg); |
| 5922 | 5790 | ||
| 5923 | ad.type = LSM_AUDIT_DATA_IPC; | 5791 | ad.type = LSM_AUDIT_DATA_IPC; |
| 5924 | ad.u.ipc_id = msq->key; | 5792 | ad.u.ipc_id = msq->key; |
| @@ -5941,11 +5809,8 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp) | |||
| 5941 | u32 sid = current_sid(); | 5809 | u32 sid = current_sid(); |
| 5942 | int rc; | 5810 | int rc; |
| 5943 | 5811 | ||
| 5944 | rc = ipc_alloc_security(shp, SECCLASS_SHM); | 5812 | isec = selinux_ipc(shp); |
| 5945 | if (rc) | 5813 | ipc_init_security(isec, SECCLASS_SHM); |
| 5946 | return rc; | ||
| 5947 | |||
| 5948 | isec = shp->security; | ||
| 5949 | 5814 | ||
| 5950 | ad.type = LSM_AUDIT_DATA_IPC; | 5815 | ad.type = LSM_AUDIT_DATA_IPC; |
| 5951 | ad.u.ipc_id = shp->key; | 5816 | ad.u.ipc_id = shp->key; |
| @@ -5953,16 +5818,7 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp) | |||
| 5953 | rc = avc_has_perm(&selinux_state, | 5818 | rc = avc_has_perm(&selinux_state, |
| 5954 | sid, isec->sid, SECCLASS_SHM, | 5819 | sid, isec->sid, SECCLASS_SHM, |
| 5955 | SHM__CREATE, &ad); | 5820 | SHM__CREATE, &ad); |
| 5956 | if (rc) { | 5821 | return rc; |
| 5957 | ipc_free_security(shp); | ||
| 5958 | return rc; | ||
| 5959 | } | ||
| 5960 | return 0; | ||
| 5961 | } | ||
| 5962 | |||
| 5963 | static void selinux_shm_free_security(struct kern_ipc_perm *shp) | ||
| 5964 | { | ||
| 5965 | ipc_free_security(shp); | ||
| 5966 | } | 5822 | } |
| 5967 | 5823 | ||
| 5968 | static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg) | 5824 | static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg) |
| @@ -5971,7 +5827,7 @@ static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg) | |||
| 5971 | struct common_audit_data ad; | 5827 | struct common_audit_data ad; |
| 5972 | u32 sid = current_sid(); | 5828 | u32 sid = current_sid(); |
| 5973 | 5829 | ||
| 5974 | isec = shp->security; | 5830 | isec = selinux_ipc(shp); |
| 5975 | 5831 | ||
| 5976 | ad.type = LSM_AUDIT_DATA_IPC; | 5832 | ad.type = LSM_AUDIT_DATA_IPC; |
| 5977 | ad.u.ipc_id = shp->key; | 5833 | ad.u.ipc_id = shp->key; |
| @@ -6038,11 +5894,8 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma) | |||
| 6038 | u32 sid = current_sid(); | 5894 | u32 sid = current_sid(); |
| 6039 | int rc; | 5895 | int rc; |
| 6040 | 5896 | ||
| 6041 | rc = ipc_alloc_security(sma, SECCLASS_SEM); | 5897 | isec = selinux_ipc(sma); |
| 6042 | if (rc) | 5898 | ipc_init_security(isec, SECCLASS_SEM); |
| 6043 | return rc; | ||
| 6044 | |||
| 6045 | isec = sma->security; | ||
| 6046 | 5899 | ||
| 6047 | ad.type = LSM_AUDIT_DATA_IPC; | 5900 | ad.type = LSM_AUDIT_DATA_IPC; |
| 6048 | ad.u.ipc_id = sma->key; | 5901 | ad.u.ipc_id = sma->key; |
| @@ -6050,16 +5903,7 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma) | |||
| 6050 | rc = avc_has_perm(&selinux_state, | 5903 | rc = avc_has_perm(&selinux_state, |
| 6051 | sid, isec->sid, SECCLASS_SEM, | 5904 | sid, isec->sid, SECCLASS_SEM, |
| 6052 | SEM__CREATE, &ad); | 5905 | SEM__CREATE, &ad); |
| 6053 | if (rc) { | 5906 | return rc; |
| 6054 | ipc_free_security(sma); | ||
| 6055 | return rc; | ||
| 6056 | } | ||
| 6057 | return 0; | ||
| 6058 | } | ||
| 6059 | |||
| 6060 | static void selinux_sem_free_security(struct kern_ipc_perm *sma) | ||
| 6061 | { | ||
| 6062 | ipc_free_security(sma); | ||
| 6063 | } | 5907 | } |
| 6064 | 5908 | ||
| 6065 | static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg) | 5909 | static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg) |
| @@ -6068,7 +5912,7 @@ static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg) | |||
| 6068 | struct common_audit_data ad; | 5912 | struct common_audit_data ad; |
| 6069 | u32 sid = current_sid(); | 5913 | u32 sid = current_sid(); |
| 6070 | 5914 | ||
| 6071 | isec = sma->security; | 5915 | isec = selinux_ipc(sma); |
| 6072 | 5916 | ||
| 6073 | ad.type = LSM_AUDIT_DATA_IPC; | 5917 | ad.type = LSM_AUDIT_DATA_IPC; |
| 6074 | ad.u.ipc_id = sma->key; | 5918 | ad.u.ipc_id = sma->key; |
| @@ -6154,7 +5998,7 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag) | |||
| 6154 | 5998 | ||
| 6155 | static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid) | 5999 | static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid) |
| 6156 | { | 6000 | { |
| 6157 | struct ipc_security_struct *isec = ipcp->security; | 6001 | struct ipc_security_struct *isec = selinux_ipc(ipcp); |
| 6158 | *secid = isec->sid; | 6002 | *secid = isec->sid; |
| 6159 | } | 6003 | } |
| 6160 | 6004 | ||
| @@ -6173,7 +6017,7 @@ static int selinux_getprocattr(struct task_struct *p, | |||
| 6173 | unsigned len; | 6017 | unsigned len; |
| 6174 | 6018 | ||
| 6175 | rcu_read_lock(); | 6019 | rcu_read_lock(); |
| 6176 | __tsec = __task_cred(p)->security; | 6020 | __tsec = selinux_cred(__task_cred(p)); |
| 6177 | 6021 | ||
| 6178 | if (current != p) { | 6022 | if (current != p) { |
| 6179 | error = avc_has_perm(&selinux_state, | 6023 | error = avc_has_perm(&selinux_state, |
| @@ -6296,7 +6140,7 @@ static int selinux_setprocattr(const char *name, void *value, size_t size) | |||
| 6296 | operation. See selinux_bprm_set_creds for the execve | 6140 | operation. See selinux_bprm_set_creds for the execve |
| 6297 | checks and may_create for the file creation checks. The | 6141 | checks and may_create for the file creation checks. The |
| 6298 | operation will then fail if the context is not permitted. */ | 6142 | operation will then fail if the context is not permitted. */ |
| 6299 | tsec = new->security; | 6143 | tsec = selinux_cred(new); |
| 6300 | if (!strcmp(name, "exec")) { | 6144 | if (!strcmp(name, "exec")) { |
| 6301 | tsec->exec_sid = sid; | 6145 | tsec->exec_sid = sid; |
| 6302 | } else if (!strcmp(name, "fscreate")) { | 6146 | } else if (!strcmp(name, "fscreate")) { |
| @@ -6380,7 +6224,7 @@ static void selinux_release_secctx(char *secdata, u32 seclen) | |||
| 6380 | 6224 | ||
| 6381 | static void selinux_inode_invalidate_secctx(struct inode *inode) | 6225 | static void selinux_inode_invalidate_secctx(struct inode *inode) |
| 6382 | { | 6226 | { |
| 6383 | struct inode_security_struct *isec = inode->i_security; | 6227 | struct inode_security_struct *isec = selinux_inode(inode); |
| 6384 | 6228 | ||
| 6385 | spin_lock(&isec->lock); | 6229 | spin_lock(&isec->lock); |
| 6386 | isec->initialized = LABEL_INVALID; | 6230 | isec->initialized = LABEL_INVALID; |
| @@ -6425,7 +6269,7 @@ static int selinux_key_alloc(struct key *k, const struct cred *cred, | |||
| 6425 | if (!ksec) | 6269 | if (!ksec) |
| 6426 | return -ENOMEM; | 6270 | return -ENOMEM; |
| 6427 | 6271 | ||
| 6428 | tsec = cred->security; | 6272 | tsec = selinux_cred(cred); |
| 6429 | if (tsec->keycreate_sid) | 6273 | if (tsec->keycreate_sid) |
| 6430 | ksec->sid = tsec->keycreate_sid; | 6274 | ksec->sid = tsec->keycreate_sid; |
| 6431 | else | 6275 | else |
| @@ -6688,6 +6532,14 @@ static void selinux_bpf_prog_free(struct bpf_prog_aux *aux) | |||
| 6688 | } | 6532 | } |
| 6689 | #endif | 6533 | #endif |
| 6690 | 6534 | ||
| 6535 | struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = { | ||
| 6536 | .lbs_cred = sizeof(struct task_security_struct), | ||
| 6537 | .lbs_file = sizeof(struct file_security_struct), | ||
| 6538 | .lbs_inode = sizeof(struct inode_security_struct), | ||
| 6539 | .lbs_ipc = sizeof(struct ipc_security_struct), | ||
| 6540 | .lbs_msg_msg = sizeof(struct msg_security_struct), | ||
| 6541 | }; | ||
| 6542 | |||
| 6691 | static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { | 6543 | static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { |
| 6692 | LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr), | 6544 | LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr), |
| 6693 | LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction), | 6545 | LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction), |
| @@ -6757,7 +6609,6 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { | |||
| 6757 | 6609 | ||
| 6758 | LSM_HOOK_INIT(file_permission, selinux_file_permission), | 6610 | LSM_HOOK_INIT(file_permission, selinux_file_permission), |
| 6759 | LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security), | 6611 | LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security), |
| 6760 | LSM_HOOK_INIT(file_free_security, selinux_file_free_security), | ||
| 6761 | LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl), | 6612 | LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl), |
| 6762 | LSM_HOOK_INIT(mmap_file, selinux_mmap_file), | 6613 | LSM_HOOK_INIT(mmap_file, selinux_mmap_file), |
| 6763 | LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr), | 6614 | LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr), |
| @@ -6771,8 +6622,6 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { | |||
| 6771 | LSM_HOOK_INIT(file_open, selinux_file_open), | 6622 | LSM_HOOK_INIT(file_open, selinux_file_open), |
| 6772 | 6623 | ||
| 6773 | LSM_HOOK_INIT(task_alloc, selinux_task_alloc), | 6624 | LSM_HOOK_INIT(task_alloc, selinux_task_alloc), |
| 6774 | LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank), | ||
| 6775 | LSM_HOOK_INIT(cred_free, selinux_cred_free), | ||
| 6776 | LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare), | 6625 | LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare), |
| 6777 | LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer), | 6626 | LSM_HOOK_INIT(cred_transfer, selinux_cred_transfer), |
| 6778 | LSM_HOOK_INIT(cred_getsecid, selinux_cred_getsecid), | 6627 | LSM_HOOK_INIT(cred_getsecid, selinux_cred_getsecid), |
| @@ -6800,24 +6649,20 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { | |||
| 6800 | LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid), | 6649 | LSM_HOOK_INIT(ipc_getsecid, selinux_ipc_getsecid), |
| 6801 | 6650 | ||
| 6802 | LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security), | 6651 | LSM_HOOK_INIT(msg_msg_alloc_security, selinux_msg_msg_alloc_security), |
| 6803 | LSM_HOOK_INIT(msg_msg_free_security, selinux_msg_msg_free_security), | ||
| 6804 | 6652 | ||
| 6805 | LSM_HOOK_INIT(msg_queue_alloc_security, | 6653 | LSM_HOOK_INIT(msg_queue_alloc_security, |
| 6806 | selinux_msg_queue_alloc_security), | 6654 | selinux_msg_queue_alloc_security), |
| 6807 | LSM_HOOK_INIT(msg_queue_free_security, selinux_msg_queue_free_security), | ||
| 6808 | LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate), | 6655 | LSM_HOOK_INIT(msg_queue_associate, selinux_msg_queue_associate), |
| 6809 | LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl), | 6656 | LSM_HOOK_INIT(msg_queue_msgctl, selinux_msg_queue_msgctl), |
| 6810 | LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd), | 6657 | LSM_HOOK_INIT(msg_queue_msgsnd, selinux_msg_queue_msgsnd), |
| 6811 | LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv), | 6658 | LSM_HOOK_INIT(msg_queue_msgrcv, selinux_msg_queue_msgrcv), |
| 6812 | 6659 | ||
| 6813 | LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security), | 6660 | LSM_HOOK_INIT(shm_alloc_security, selinux_shm_alloc_security), |
| 6814 | LSM_HOOK_INIT(shm_free_security, selinux_shm_free_security), | ||
| 6815 | LSM_HOOK_INIT(shm_associate, selinux_shm_associate), | 6661 | LSM_HOOK_INIT(shm_associate, selinux_shm_associate), |
| 6816 | LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl), | 6662 | LSM_HOOK_INIT(shm_shmctl, selinux_shm_shmctl), |
| 6817 | LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat), | 6663 | LSM_HOOK_INIT(shm_shmat, selinux_shm_shmat), |
| 6818 | 6664 | ||
| 6819 | LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security), | 6665 | LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security), |
| 6820 | LSM_HOOK_INIT(sem_free_security, selinux_sem_free_security), | ||
| 6821 | LSM_HOOK_INIT(sem_associate, selinux_sem_associate), | 6666 | LSM_HOOK_INIT(sem_associate, selinux_sem_associate), |
| 6822 | LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl), | 6667 | LSM_HOOK_INIT(sem_semctl, selinux_sem_semctl), |
| 6823 | LSM_HOOK_INIT(sem_semop, selinux_sem_semop), | 6668 | LSM_HOOK_INIT(sem_semop, selinux_sem_semop), |
| @@ -6928,16 +6773,6 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { | |||
| 6928 | 6773 | ||
| 6929 | static __init int selinux_init(void) | 6774 | static __init int selinux_init(void) |
| 6930 | { | 6775 | { |
| 6931 | if (!security_module_enable("selinux")) { | ||
| 6932 | selinux_enabled = 0; | ||
| 6933 | return 0; | ||
| 6934 | } | ||
| 6935 | |||
| 6936 | if (!selinux_enabled) { | ||
| 6937 | pr_info("SELinux: Disabled at boot.\n"); | ||
| 6938 | return 0; | ||
| 6939 | } | ||
| 6940 | |||
| 6941 | pr_info("SELinux: Initializing.\n"); | 6776 | pr_info("SELinux: Initializing.\n"); |
| 6942 | 6777 | ||
| 6943 | memset(&selinux_state, 0, sizeof(selinux_state)); | 6778 | memset(&selinux_state, 0, sizeof(selinux_state)); |
| @@ -6951,12 +6786,6 @@ static __init int selinux_init(void) | |||
| 6951 | 6786 | ||
| 6952 | default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC); | 6787 | default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC); |
| 6953 | 6788 | ||
| 6954 | sel_inode_cache = kmem_cache_create("selinux_inode_security", | ||
| 6955 | sizeof(struct inode_security_struct), | ||
| 6956 | 0, SLAB_PANIC, NULL); | ||
| 6957 | file_security_cache = kmem_cache_create("selinux_file_security", | ||
| 6958 | sizeof(struct file_security_struct), | ||
| 6959 | 0, SLAB_PANIC, NULL); | ||
| 6960 | avc_init(); | 6789 | avc_init(); |
| 6961 | 6790 | ||
| 6962 | avtab_cache_init(); | 6791 | avtab_cache_init(); |
| @@ -6999,6 +6828,9 @@ void selinux_complete_init(void) | |||
| 6999 | all processes and objects when they are created. */ | 6828 | all processes and objects when they are created. */ |
| 7000 | DEFINE_LSM(selinux) = { | 6829 | DEFINE_LSM(selinux) = { |
| 7001 | .name = "selinux", | 6830 | .name = "selinux", |
| 6831 | .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE, | ||
| 6832 | .enabled = &selinux_enabled, | ||
| 6833 | .blobs = &selinux_blob_sizes, | ||
| 7002 | .init = selinux_init, | 6834 | .init = selinux_init, |
| 7003 | }; | 6835 | }; |
| 7004 | 6836 | ||
diff --git a/security/selinux/include/audit.h b/security/selinux/include/audit.h index 1bdf973433cc..36e1d44c0209 100644 --- a/security/selinux/include/audit.h +++ b/security/selinux/include/audit.h | |||
| @@ -1,9 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * SELinux support for the Audit LSM hooks | 2 | * SELinux support for the Audit LSM hooks |
| 3 | * | 3 | * |
| 4 | * Most of below header was moved from include/linux/selinux.h which | ||
| 5 | * is released under below copyrights: | ||
| 6 | * | ||
| 7 | * Author: James Morris <jmorris@redhat.com> | 4 | * Author: James Morris <jmorris@redhat.com> |
| 8 | * | 5 | * |
| 9 | * Copyright (C) 2005 Red Hat, Inc., James Morris <jmorris@redhat.com> | 6 | * Copyright (C) 2005 Red Hat, Inc., James Morris <jmorris@redhat.com> |
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index cc5e26b0161b..231262d8eac9 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h | |||
| @@ -25,6 +25,8 @@ | |||
| 25 | #include <linux/binfmts.h> | 25 | #include <linux/binfmts.h> |
| 26 | #include <linux/in.h> | 26 | #include <linux/in.h> |
| 27 | #include <linux/spinlock.h> | 27 | #include <linux/spinlock.h> |
| 28 | #include <linux/lsm_hooks.h> | ||
| 29 | #include <linux/msg.h> | ||
| 28 | #include <net/net_namespace.h> | 30 | #include <net/net_namespace.h> |
| 29 | #include "flask.h" | 31 | #include "flask.h" |
| 30 | #include "avc.h" | 32 | #include "avc.h" |
| @@ -56,10 +58,7 @@ enum label_initialized { | |||
| 56 | 58 | ||
| 57 | struct inode_security_struct { | 59 | struct inode_security_struct { |
| 58 | struct inode *inode; /* back pointer to inode object */ | 60 | struct inode *inode; /* back pointer to inode object */ |
| 59 | union { | 61 | struct list_head list; /* list of inode_security_struct */ |
| 60 | struct list_head list; /* list of inode_security_struct */ | ||
| 61 | struct rcu_head rcu; /* for freeing the inode_security_struct */ | ||
| 62 | }; | ||
| 63 | u32 task_sid; /* SID of creating task */ | 62 | u32 task_sid; /* SID of creating task */ |
| 64 | u32 sid; /* SID of this object */ | 63 | u32 sid; /* SID of this object */ |
| 65 | u16 sclass; /* security class of this object */ | 64 | u16 sclass; /* security class of this object */ |
| @@ -158,4 +157,35 @@ struct bpf_security_struct { | |||
| 158 | u32 sid; /*SID of bpf obj creater*/ | 157 | u32 sid; /*SID of bpf obj creater*/ |
| 159 | }; | 158 | }; |
| 160 | 159 | ||
| 160 | extern struct lsm_blob_sizes selinux_blob_sizes; | ||
| 161 | static inline struct task_security_struct *selinux_cred(const struct cred *cred) | ||
| 162 | { | ||
| 163 | return cred->security + selinux_blob_sizes.lbs_cred; | ||
| 164 | } | ||
| 165 | |||
| 166 | static inline struct file_security_struct *selinux_file(const struct file *file) | ||
| 167 | { | ||
| 168 | return file->f_security + selinux_blob_sizes.lbs_file; | ||
| 169 | } | ||
| 170 | |||
| 171 | static inline struct inode_security_struct *selinux_inode( | ||
| 172 | const struct inode *inode) | ||
| 173 | { | ||
| 174 | if (unlikely(!inode->i_security)) | ||
| 175 | return NULL; | ||
| 176 | return inode->i_security + selinux_blob_sizes.lbs_inode; | ||
| 177 | } | ||
| 178 | |||
| 179 | static inline struct msg_security_struct *selinux_msg_msg( | ||
| 180 | const struct msg_msg *msg_msg) | ||
| 181 | { | ||
| 182 | return msg_msg->security + selinux_blob_sizes.lbs_msg_msg; | ||
| 183 | } | ||
| 184 | |||
| 185 | static inline struct ipc_security_struct *selinux_ipc( | ||
| 186 | const struct kern_ipc_perm *ipc) | ||
| 187 | { | ||
| 188 | return ipc->security + selinux_blob_sizes.lbs_ipc; | ||
| 189 | } | ||
| 190 | |||
| 161 | #endif /* _SELINUX_OBJSEC_H_ */ | 191 | #endif /* _SELINUX_OBJSEC_H_ */ |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index f3a5a138a096..145ee62f205a 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
| @@ -1378,7 +1378,7 @@ static int sel_make_bools(struct selinux_fs_info *fsi) | |||
| 1378 | goto out; | 1378 | goto out; |
| 1379 | } | 1379 | } |
| 1380 | 1380 | ||
| 1381 | isec = (struct inode_security_struct *)inode->i_security; | 1381 | isec = selinux_inode(inode); |
| 1382 | ret = security_genfs_sid(fsi->state, "selinuxfs", page, | 1382 | ret = security_genfs_sid(fsi->state, "selinuxfs", page, |
| 1383 | SECCLASS_FILE, &sid); | 1383 | SECCLASS_FILE, &sid); |
| 1384 | if (ret) { | 1384 | if (ret) { |
| @@ -1953,7 +1953,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
| 1953 | } | 1953 | } |
| 1954 | 1954 | ||
| 1955 | inode->i_ino = ++fsi->last_ino; | 1955 | inode->i_ino = ++fsi->last_ino; |
| 1956 | isec = (struct inode_security_struct *)inode->i_security; | 1956 | isec = selinux_inode(inode); |
| 1957 | isec->sid = SECINITSID_DEVNULL; | 1957 | isec->sid = SECINITSID_DEVNULL; |
| 1958 | isec->sclass = SECCLASS_CHR_FILE; | 1958 | isec->sclass = SECCLASS_CHR_FILE; |
| 1959 | isec->initialized = LABEL_INITIALIZED; | 1959 | isec->initialized = LABEL_INITIALIZED; |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index dd44126c8d14..d6e7b4856d93 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
| @@ -49,7 +49,6 @@ | |||
| 49 | #include <linux/sched.h> | 49 | #include <linux/sched.h> |
| 50 | #include <linux/audit.h> | 50 | #include <linux/audit.h> |
| 51 | #include <linux/mutex.h> | 51 | #include <linux/mutex.h> |
| 52 | #include <linux/selinux.h> | ||
| 53 | #include <linux/flex_array.h> | 52 | #include <linux/flex_array.h> |
| 54 | #include <linux/vmalloc.h> | 53 | #include <linux/vmalloc.h> |
| 55 | #include <net/netlabel.h> | 54 | #include <net/netlabel.h> |
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index bd7d18bdb147..7c57cb7e4146 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c | |||
| @@ -79,7 +79,7 @@ static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp, | |||
| 79 | gfp_t gfp) | 79 | gfp_t gfp) |
| 80 | { | 80 | { |
| 81 | int rc; | 81 | int rc; |
| 82 | const struct task_security_struct *tsec = current_security(); | 82 | const struct task_security_struct *tsec = selinux_cred(current_cred()); |
| 83 | struct xfrm_sec_ctx *ctx = NULL; | 83 | struct xfrm_sec_ctx *ctx = NULL; |
| 84 | u32 str_len; | 84 | u32 str_len; |
| 85 | 85 | ||
| @@ -138,7 +138,7 @@ static void selinux_xfrm_free(struct xfrm_sec_ctx *ctx) | |||
| 138 | */ | 138 | */ |
| 139 | static int selinux_xfrm_delete(struct xfrm_sec_ctx *ctx) | 139 | static int selinux_xfrm_delete(struct xfrm_sec_ctx *ctx) |
| 140 | { | 140 | { |
| 141 | const struct task_security_struct *tsec = current_security(); | 141 | const struct task_security_struct *tsec = selinux_cred(current_cred()); |
| 142 | 142 | ||
| 143 | if (!ctx) | 143 | if (!ctx) |
| 144 | return 0; | 144 | return 0; |
diff --git a/security/smack/smack.h b/security/smack/smack.h index f7db791fb566..9c7c95a5c497 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
| 25 | #include <linux/rculist.h> | 25 | #include <linux/rculist.h> |
| 26 | #include <linux/lsm_audit.h> | 26 | #include <linux/lsm_audit.h> |
| 27 | #include <linux/msg.h> | ||
| 27 | 28 | ||
| 28 | /* | 29 | /* |
| 29 | * Use IPv6 port labeling if IPv6 is enabled and secmarks | 30 | * Use IPv6 port labeling if IPv6 is enabled and secmarks |
| @@ -336,6 +337,7 @@ extern struct smack_known *smack_syslog_label; | |||
| 336 | extern struct smack_known *smack_unconfined; | 337 | extern struct smack_known *smack_unconfined; |
| 337 | #endif | 338 | #endif |
| 338 | extern int smack_ptrace_rule; | 339 | extern int smack_ptrace_rule; |
| 340 | extern struct lsm_blob_sizes smack_blob_sizes; | ||
| 339 | 341 | ||
| 340 | extern struct smack_known smack_known_floor; | 342 | extern struct smack_known smack_known_floor; |
| 341 | extern struct smack_known smack_known_hat; | 343 | extern struct smack_known smack_known_hat; |
| @@ -356,12 +358,38 @@ extern struct list_head smack_onlycap_list; | |||
| 356 | #define SMACK_HASH_SLOTS 16 | 358 | #define SMACK_HASH_SLOTS 16 |
| 357 | extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS]; | 359 | extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS]; |
| 358 | 360 | ||
| 361 | static inline struct task_smack *smack_cred(const struct cred *cred) | ||
| 362 | { | ||
| 363 | return cred->security + smack_blob_sizes.lbs_cred; | ||
| 364 | } | ||
| 365 | |||
| 366 | static inline struct smack_known **smack_file(const struct file *file) | ||
| 367 | { | ||
| 368 | return (struct smack_known **)(file->f_security + | ||
| 369 | smack_blob_sizes.lbs_file); | ||
| 370 | } | ||
| 371 | |||
| 372 | static inline struct inode_smack *smack_inode(const struct inode *inode) | ||
| 373 | { | ||
| 374 | return inode->i_security + smack_blob_sizes.lbs_inode; | ||
| 375 | } | ||
| 376 | |||
| 377 | static inline struct smack_known **smack_msg_msg(const struct msg_msg *msg) | ||
| 378 | { | ||
| 379 | return msg->security + smack_blob_sizes.lbs_msg_msg; | ||
| 380 | } | ||
| 381 | |||
| 382 | static inline struct smack_known **smack_ipc(const struct kern_ipc_perm *ipc) | ||
| 383 | { | ||
| 384 | return ipc->security + smack_blob_sizes.lbs_ipc; | ||
| 385 | } | ||
| 386 | |||
| 359 | /* | 387 | /* |
| 360 | * Is the directory transmuting? | 388 | * Is the directory transmuting? |
| 361 | */ | 389 | */ |
| 362 | static inline int smk_inode_transmutable(const struct inode *isp) | 390 | static inline int smk_inode_transmutable(const struct inode *isp) |
| 363 | { | 391 | { |
| 364 | struct inode_smack *sip = isp->i_security; | 392 | struct inode_smack *sip = smack_inode(isp); |
| 365 | return (sip->smk_flags & SMK_INODE_TRANSMUTE) != 0; | 393 | return (sip->smk_flags & SMK_INODE_TRANSMUTE) != 0; |
| 366 | } | 394 | } |
| 367 | 395 | ||
| @@ -370,7 +398,7 @@ static inline int smk_inode_transmutable(const struct inode *isp) | |||
| 370 | */ | 398 | */ |
| 371 | static inline struct smack_known *smk_of_inode(const struct inode *isp) | 399 | static inline struct smack_known *smk_of_inode(const struct inode *isp) |
| 372 | { | 400 | { |
| 373 | struct inode_smack *sip = isp->i_security; | 401 | struct inode_smack *sip = smack_inode(isp); |
| 374 | return sip->smk_inode; | 402 | return sip->smk_inode; |
| 375 | } | 403 | } |
| 376 | 404 | ||
| @@ -382,13 +410,19 @@ static inline struct smack_known *smk_of_task(const struct task_smack *tsp) | |||
| 382 | return tsp->smk_task; | 410 | return tsp->smk_task; |
| 383 | } | 411 | } |
| 384 | 412 | ||
| 385 | static inline struct smack_known *smk_of_task_struct(const struct task_struct *t) | 413 | static inline struct smack_known *smk_of_task_struct( |
| 414 | const struct task_struct *t) | ||
| 386 | { | 415 | { |
| 387 | struct smack_known *skp; | 416 | struct smack_known *skp; |
| 417 | const struct cred *cred; | ||
| 388 | 418 | ||
| 389 | rcu_read_lock(); | 419 | rcu_read_lock(); |
| 390 | skp = smk_of_task(__task_cred(t)->security); | 420 | |
| 421 | cred = __task_cred(t); | ||
| 422 | skp = smk_of_task(smack_cred(cred)); | ||
| 423 | |||
| 391 | rcu_read_unlock(); | 424 | rcu_read_unlock(); |
| 425 | |||
| 392 | return skp; | 426 | return skp; |
| 393 | } | 427 | } |
| 394 | 428 | ||
| @@ -405,7 +439,7 @@ static inline struct smack_known *smk_of_forked(const struct task_smack *tsp) | |||
| 405 | */ | 439 | */ |
| 406 | static inline struct smack_known *smk_of_current(void) | 440 | static inline struct smack_known *smk_of_current(void) |
| 407 | { | 441 | { |
| 408 | return smk_of_task(current_security()); | 442 | return smk_of_task(smack_cred(current_cred())); |
| 409 | } | 443 | } |
| 410 | 444 | ||
| 411 | /* | 445 | /* |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 9a4c0ad46518..fe2ce3a65822 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
| @@ -275,7 +275,7 @@ out_audit: | |||
| 275 | int smk_curacc(struct smack_known *obj_known, | 275 | int smk_curacc(struct smack_known *obj_known, |
| 276 | u32 mode, struct smk_audit_info *a) | 276 | u32 mode, struct smk_audit_info *a) |
| 277 | { | 277 | { |
| 278 | struct task_smack *tsp = current_security(); | 278 | struct task_smack *tsp = smack_cred(current_cred()); |
| 279 | 279 | ||
| 280 | return smk_tskacc(tsp, obj_known, mode, a); | 280 | return smk_tskacc(tsp, obj_known, mode, a); |
| 281 | } | 281 | } |
| @@ -635,12 +635,12 @@ DEFINE_MUTEX(smack_onlycap_lock); | |||
| 635 | */ | 635 | */ |
| 636 | bool smack_privileged_cred(int cap, const struct cred *cred) | 636 | bool smack_privileged_cred(int cap, const struct cred *cred) |
| 637 | { | 637 | { |
| 638 | struct task_smack *tsp = cred->security; | 638 | struct task_smack *tsp = smack_cred(cred); |
| 639 | struct smack_known *skp = tsp->smk_task; | 639 | struct smack_known *skp = tsp->smk_task; |
| 640 | struct smack_known_list_elem *sklep; | 640 | struct smack_known_list_elem *sklep; |
| 641 | int rc; | 641 | int rc; |
| 642 | 642 | ||
| 643 | rc = cap_capable(cred, &init_user_ns, cap, SECURITY_CAP_AUDIT); | 643 | rc = cap_capable(cred, &init_user_ns, cap, CAP_OPT_NONE); |
| 644 | if (rc) | 644 | if (rc) |
| 645 | return false; | 645 | return false; |
| 646 | 646 | ||
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 430d4f35e55c..2309c696c6c8 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
| @@ -139,7 +139,7 @@ static int smk_bu_note(char *note, struct smack_known *sskp, | |||
| 139 | static int smk_bu_current(char *note, struct smack_known *oskp, | 139 | static int smk_bu_current(char *note, struct smack_known *oskp, |
| 140 | int mode, int rc) | 140 | int mode, int rc) |
| 141 | { | 141 | { |
| 142 | struct task_smack *tsp = current_security(); | 142 | struct task_smack *tsp = smack_cred(current_cred()); |
| 143 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | 143 | char acc[SMK_NUM_ACCESS_TYPE + 1]; |
| 144 | 144 | ||
| 145 | if (rc <= 0) | 145 | if (rc <= 0) |
| @@ -160,7 +160,7 @@ static int smk_bu_current(char *note, struct smack_known *oskp, | |||
| 160 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | 160 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP |
| 161 | static int smk_bu_task(struct task_struct *otp, int mode, int rc) | 161 | static int smk_bu_task(struct task_struct *otp, int mode, int rc) |
| 162 | { | 162 | { |
| 163 | struct task_smack *tsp = current_security(); | 163 | struct task_smack *tsp = smack_cred(current_cred()); |
| 164 | struct smack_known *smk_task = smk_of_task_struct(otp); | 164 | struct smack_known *smk_task = smk_of_task_struct(otp); |
| 165 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | 165 | char acc[SMK_NUM_ACCESS_TYPE + 1]; |
| 166 | 166 | ||
| @@ -182,8 +182,8 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc) | |||
| 182 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | 182 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP |
| 183 | static int smk_bu_inode(struct inode *inode, int mode, int rc) | 183 | static int smk_bu_inode(struct inode *inode, int mode, int rc) |
| 184 | { | 184 | { |
| 185 | struct task_smack *tsp = current_security(); | 185 | struct task_smack *tsp = smack_cred(current_cred()); |
| 186 | struct inode_smack *isp = inode->i_security; | 186 | struct inode_smack *isp = smack_inode(inode); |
| 187 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | 187 | char acc[SMK_NUM_ACCESS_TYPE + 1]; |
| 188 | 188 | ||
| 189 | if (isp->smk_flags & SMK_INODE_IMPURE) | 189 | if (isp->smk_flags & SMK_INODE_IMPURE) |
| @@ -212,10 +212,10 @@ static int smk_bu_inode(struct inode *inode, int mode, int rc) | |||
| 212 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP | 212 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP |
| 213 | static int smk_bu_file(struct file *file, int mode, int rc) | 213 | static int smk_bu_file(struct file *file, int mode, int rc) |
| 214 | { | 214 | { |
| 215 | struct task_smack *tsp = current_security(); | 215 | struct task_smack *tsp = smack_cred(current_cred()); |
| 216 | struct smack_known *sskp = tsp->smk_task; | 216 | struct smack_known *sskp = tsp->smk_task; |
| 217 | struct inode *inode = file_inode(file); | 217 | struct inode *inode = file_inode(file); |
| 218 | struct inode_smack *isp = inode->i_security; | 218 | struct inode_smack *isp = smack_inode(inode); |
| 219 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | 219 | char acc[SMK_NUM_ACCESS_TYPE + 1]; |
| 220 | 220 | ||
| 221 | if (isp->smk_flags & SMK_INODE_IMPURE) | 221 | if (isp->smk_flags & SMK_INODE_IMPURE) |
| @@ -242,10 +242,10 @@ static int smk_bu_file(struct file *file, int mode, int rc) | |||
| 242 | static int smk_bu_credfile(const struct cred *cred, struct file *file, | 242 | static int smk_bu_credfile(const struct cred *cred, struct file *file, |
| 243 | int mode, int rc) | 243 | int mode, int rc) |
| 244 | { | 244 | { |
| 245 | struct task_smack *tsp = cred->security; | 245 | struct task_smack *tsp = smack_cred(cred); |
| 246 | struct smack_known *sskp = tsp->smk_task; | 246 | struct smack_known *sskp = tsp->smk_task; |
| 247 | struct inode *inode = file_inode(file); | 247 | struct inode *inode = file_inode(file); |
| 248 | struct inode_smack *isp = inode->i_security; | 248 | struct inode_smack *isp = smack_inode(inode); |
| 249 | char acc[SMK_NUM_ACCESS_TYPE + 1]; | 249 | char acc[SMK_NUM_ACCESS_TYPE + 1]; |
| 250 | 250 | ||
| 251 | if (isp->smk_flags & SMK_INODE_IMPURE) | 251 | if (isp->smk_flags & SMK_INODE_IMPURE) |
| @@ -305,50 +305,35 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip, | |||
| 305 | } | 305 | } |
| 306 | 306 | ||
| 307 | /** | 307 | /** |
| 308 | * new_inode_smack - allocate an inode security blob | 308 | * init_inode_smack - initialize an inode security blob |
| 309 | * @isp: the blob to initialize | ||
| 309 | * @skp: a pointer to the Smack label entry to use in the blob | 310 | * @skp: a pointer to the Smack label entry to use in the blob |
| 310 | * | 311 | * |
| 311 | * Returns the new blob or NULL if there's no memory available | ||
| 312 | */ | 312 | */ |
| 313 | static struct inode_smack *new_inode_smack(struct smack_known *skp) | 313 | static void init_inode_smack(struct inode *inode, struct smack_known *skp) |
| 314 | { | 314 | { |
| 315 | struct inode_smack *isp; | 315 | struct inode_smack *isp = smack_inode(inode); |
| 316 | |||
| 317 | isp = kmem_cache_zalloc(smack_inode_cache, GFP_NOFS); | ||
| 318 | if (isp == NULL) | ||
| 319 | return NULL; | ||
| 320 | 316 | ||
| 321 | isp->smk_inode = skp; | 317 | isp->smk_inode = skp; |
| 322 | isp->smk_flags = 0; | 318 | isp->smk_flags = 0; |
| 323 | mutex_init(&isp->smk_lock); | 319 | mutex_init(&isp->smk_lock); |
| 324 | |||
| 325 | return isp; | ||
| 326 | } | 320 | } |
| 327 | 321 | ||
| 328 | /** | 322 | /** |
| 329 | * new_task_smack - allocate a task security blob | 323 | * init_task_smack - initialize a task security blob |
| 324 | * @tsp: blob to initialize | ||
| 330 | * @task: a pointer to the Smack label for the running task | 325 | * @task: a pointer to the Smack label for the running task |
| 331 | * @forked: a pointer to the Smack label for the forked task | 326 | * @forked: a pointer to the Smack label for the forked task |
| 332 | * @gfp: type of the memory for the allocation | ||
| 333 | * | 327 | * |
| 334 | * Returns the new blob or NULL if there's no memory available | ||
| 335 | */ | 328 | */ |
| 336 | static struct task_smack *new_task_smack(struct smack_known *task, | 329 | static void init_task_smack(struct task_smack *tsp, struct smack_known *task, |
| 337 | struct smack_known *forked, gfp_t gfp) | 330 | struct smack_known *forked) |
| 338 | { | 331 | { |
| 339 | struct task_smack *tsp; | ||
| 340 | |||
| 341 | tsp = kzalloc(sizeof(struct task_smack), gfp); | ||
| 342 | if (tsp == NULL) | ||
| 343 | return NULL; | ||
| 344 | |||
| 345 | tsp->smk_task = task; | 332 | tsp->smk_task = task; |
| 346 | tsp->smk_forked = forked; | 333 | tsp->smk_forked = forked; |
| 347 | INIT_LIST_HEAD(&tsp->smk_rules); | 334 | INIT_LIST_HEAD(&tsp->smk_rules); |
| 348 | INIT_LIST_HEAD(&tsp->smk_relabel); | 335 | INIT_LIST_HEAD(&tsp->smk_relabel); |
| 349 | mutex_init(&tsp->smk_rules_lock); | 336 | mutex_init(&tsp->smk_rules_lock); |
| 350 | |||
| 351 | return tsp; | ||
| 352 | } | 337 | } |
| 353 | 338 | ||
| 354 | /** | 339 | /** |
| @@ -448,7 +433,7 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, | |||
| 448 | 433 | ||
| 449 | rcu_read_lock(); | 434 | rcu_read_lock(); |
| 450 | tracercred = __task_cred(tracer); | 435 | tracercred = __task_cred(tracer); |
| 451 | tsp = tracercred->security; | 436 | tsp = smack_cred(tracercred); |
| 452 | tracer_known = smk_of_task(tsp); | 437 | tracer_known = smk_of_task(tsp); |
| 453 | 438 | ||
| 454 | if ((mode & PTRACE_MODE_ATTACH) && | 439 | if ((mode & PTRACE_MODE_ATTACH) && |
| @@ -515,7 +500,7 @@ static int smack_ptrace_traceme(struct task_struct *ptp) | |||
| 515 | int rc; | 500 | int rc; |
| 516 | struct smack_known *skp; | 501 | struct smack_known *skp; |
| 517 | 502 | ||
| 518 | skp = smk_of_task(current_security()); | 503 | skp = smk_of_task(smack_cred(current_cred())); |
| 519 | 504 | ||
| 520 | rc = smk_ptrace_rule_check(ptp, skp, PTRACE_MODE_ATTACH, __func__); | 505 | rc = smk_ptrace_rule_check(ptp, skp, PTRACE_MODE_ATTACH, __func__); |
| 521 | return rc; | 506 | return rc; |
| @@ -718,6 +703,13 @@ static int smack_set_mnt_opts(struct super_block *sb, | |||
| 718 | if (sp->smk_flags & SMK_SB_INITIALIZED) | 703 | if (sp->smk_flags & SMK_SB_INITIALIZED) |
| 719 | return 0; | 704 | return 0; |
| 720 | 705 | ||
| 706 | if (inode->i_security == NULL) { | ||
| 707 | int rc = lsm_inode_alloc(inode); | ||
| 708 | |||
| 709 | if (rc) | ||
| 710 | return rc; | ||
| 711 | } | ||
| 712 | |||
| 721 | if (!smack_privileged(CAP_MAC_ADMIN)) { | 713 | if (!smack_privileged(CAP_MAC_ADMIN)) { |
| 722 | /* | 714 | /* |
| 723 | * Unprivileged mounts don't get to specify Smack values. | 715 | * Unprivileged mounts don't get to specify Smack values. |
| @@ -782,17 +774,12 @@ static int smack_set_mnt_opts(struct super_block *sb, | |||
| 782 | /* | 774 | /* |
| 783 | * Initialize the root inode. | 775 | * Initialize the root inode. |
| 784 | */ | 776 | */ |
| 785 | isp = inode->i_security; | 777 | init_inode_smack(inode, sp->smk_root); |
| 786 | if (isp == NULL) { | ||
| 787 | isp = new_inode_smack(sp->smk_root); | ||
| 788 | if (isp == NULL) | ||
| 789 | return -ENOMEM; | ||
| 790 | inode->i_security = isp; | ||
| 791 | } else | ||
| 792 | isp->smk_inode = sp->smk_root; | ||
| 793 | 778 | ||
| 794 | if (transmute) | 779 | if (transmute) { |
| 780 | isp = smack_inode(inode); | ||
| 795 | isp->smk_flags |= SMK_INODE_TRANSMUTE; | 781 | isp->smk_flags |= SMK_INODE_TRANSMUTE; |
| 782 | } | ||
| 796 | 783 | ||
| 797 | return 0; | 784 | return 0; |
| 798 | } | 785 | } |
| @@ -831,7 +818,7 @@ static int smack_sb_statfs(struct dentry *dentry) | |||
| 831 | static int smack_bprm_set_creds(struct linux_binprm *bprm) | 818 | static int smack_bprm_set_creds(struct linux_binprm *bprm) |
| 832 | { | 819 | { |
| 833 | struct inode *inode = file_inode(bprm->file); | 820 | struct inode *inode = file_inode(bprm->file); |
| 834 | struct task_smack *bsp = bprm->cred->security; | 821 | struct task_smack *bsp = smack_cred(bprm->cred); |
| 835 | struct inode_smack *isp; | 822 | struct inode_smack *isp; |
| 836 | struct superblock_smack *sbsp; | 823 | struct superblock_smack *sbsp; |
| 837 | int rc; | 824 | int rc; |
| @@ -839,7 +826,7 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm) | |||
| 839 | if (bprm->called_set_creds) | 826 | if (bprm->called_set_creds) |
| 840 | return 0; | 827 | return 0; |
| 841 | 828 | ||
| 842 | isp = inode->i_security; | 829 | isp = smack_inode(inode); |
| 843 | if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task) | 830 | if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task) |
| 844 | return 0; | 831 | return 0; |
| 845 | 832 | ||
| @@ -890,49 +877,11 @@ static int smack_inode_alloc_security(struct inode *inode) | |||
| 890 | { | 877 | { |
| 891 | struct smack_known *skp = smk_of_current(); | 878 | struct smack_known *skp = smk_of_current(); |
| 892 | 879 | ||
| 893 | inode->i_security = new_inode_smack(skp); | 880 | init_inode_smack(inode, skp); |
| 894 | if (inode->i_security == NULL) | ||
| 895 | return -ENOMEM; | ||
| 896 | return 0; | 881 | return 0; |
| 897 | } | 882 | } |
| 898 | 883 | ||
| 899 | /** | 884 | /** |
| 900 | * smack_inode_free_rcu - Free inode_smack blob from cache | ||
| 901 | * @head: the rcu_head for getting inode_smack pointer | ||
| 902 | * | ||
| 903 | * Call back function called from call_rcu() to free | ||
| 904 | * the i_security blob pointer in inode | ||
| 905 | */ | ||
| 906 | static void smack_inode_free_rcu(struct rcu_head *head) | ||
| 907 | { | ||
| 908 | struct inode_smack *issp; | ||
| 909 | |||
| 910 | issp = container_of(head, struct inode_smack, smk_rcu); | ||
| 911 | kmem_cache_free(smack_inode_cache, issp); | ||
| 912 | } | ||
| 913 | |||
| 914 | /** | ||
| 915 | * smack_inode_free_security - free an inode blob using call_rcu() | ||
| 916 | * @inode: the inode with a blob | ||
| 917 | * | ||
| 918 | * Clears the blob pointer in inode using RCU | ||
| 919 | */ | ||
| 920 | static void smack_inode_free_security(struct inode *inode) | ||
| 921 | { | ||
| 922 | struct inode_smack *issp = inode->i_security; | ||
| 923 | |||
| 924 | /* | ||
| 925 | * The inode may still be referenced in a path walk and | ||
| 926 | * a call to smack_inode_permission() can be made | ||
| 927 | * after smack_inode_free_security() is called. | ||
| 928 | * To avoid race condition free the i_security via RCU | ||
| 929 | * and leave the current inode->i_security pointer intact. | ||
| 930 | * The inode will be freed after the RCU grace period too. | ||
| 931 | */ | ||
| 932 | call_rcu(&issp->smk_rcu, smack_inode_free_rcu); | ||
| 933 | } | ||
| 934 | |||
| 935 | /** | ||
| 936 | * smack_inode_init_security - copy out the smack from an inode | 885 | * smack_inode_init_security - copy out the smack from an inode |
| 937 | * @inode: the newly created inode | 886 | * @inode: the newly created inode |
| 938 | * @dir: containing directory object | 887 | * @dir: containing directory object |
| @@ -947,7 +896,7 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
| 947 | const struct qstr *qstr, const char **name, | 896 | const struct qstr *qstr, const char **name, |
| 948 | void **value, size_t *len) | 897 | void **value, size_t *len) |
| 949 | { | 898 | { |
| 950 | struct inode_smack *issp = inode->i_security; | 899 | struct inode_smack *issp = smack_inode(inode); |
| 951 | struct smack_known *skp = smk_of_current(); | 900 | struct smack_known *skp = smk_of_current(); |
| 952 | struct smack_known *isp = smk_of_inode(inode); | 901 | struct smack_known *isp = smk_of_inode(inode); |
| 953 | struct smack_known *dsp = smk_of_inode(dir); | 902 | struct smack_known *dsp = smk_of_inode(dir); |
| @@ -1285,7 +1234,7 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
| 1285 | const void *value, size_t size, int flags) | 1234 | const void *value, size_t size, int flags) |
| 1286 | { | 1235 | { |
| 1287 | struct smack_known *skp; | 1236 | struct smack_known *skp; |
| 1288 | struct inode_smack *isp = d_backing_inode(dentry)->i_security; | 1237 | struct inode_smack *isp = smack_inode(d_backing_inode(dentry)); |
| 1289 | 1238 | ||
| 1290 | if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { | 1239 | if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { |
| 1291 | isp->smk_flags |= SMK_INODE_TRANSMUTE; | 1240 | isp->smk_flags |= SMK_INODE_TRANSMUTE; |
| @@ -1366,7 +1315,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) | |||
| 1366 | if (rc != 0) | 1315 | if (rc != 0) |
| 1367 | return rc; | 1316 | return rc; |
| 1368 | 1317 | ||
| 1369 | isp = d_backing_inode(dentry)->i_security; | 1318 | isp = smack_inode(d_backing_inode(dentry)); |
| 1370 | /* | 1319 | /* |
| 1371 | * Don't do anything special for these. | 1320 | * Don't do anything special for these. |
| 1372 | * XATTR_NAME_SMACKIPIN | 1321 | * XATTR_NAME_SMACKIPIN |
| @@ -1498,25 +1447,13 @@ static void smack_inode_getsecid(struct inode *inode, u32 *secid) | |||
| 1498 | */ | 1447 | */ |
| 1499 | static int smack_file_alloc_security(struct file *file) | 1448 | static int smack_file_alloc_security(struct file *file) |
| 1500 | { | 1449 | { |
| 1501 | struct smack_known *skp = smk_of_current(); | 1450 | struct smack_known **blob = smack_file(file); |
| 1502 | 1451 | ||
| 1503 | file->f_security = skp; | 1452 | *blob = smk_of_current(); |
| 1504 | return 0; | 1453 | return 0; |
| 1505 | } | 1454 | } |
| 1506 | 1455 | ||
| 1507 | /** | 1456 | /** |
| 1508 | * smack_file_free_security - clear a file security blob | ||
| 1509 | * @file: the object | ||
| 1510 | * | ||
| 1511 | * The security blob for a file is a pointer to the master | ||
| 1512 | * label list, so no memory is freed. | ||
| 1513 | */ | ||
| 1514 | static void smack_file_free_security(struct file *file) | ||
| 1515 | { | ||
| 1516 | file->f_security = NULL; | ||
| 1517 | } | ||
| 1518 | |||
| 1519 | /** | ||
| 1520 | * smack_file_ioctl - Smack check on ioctls | 1457 | * smack_file_ioctl - Smack check on ioctls |
| 1521 | * @file: the object | 1458 | * @file: the object |
| 1522 | * @cmd: what to do | 1459 | * @cmd: what to do |
| @@ -1653,7 +1590,7 @@ static int smack_mmap_file(struct file *file, | |||
| 1653 | if (unlikely(IS_PRIVATE(file_inode(file)))) | 1590 | if (unlikely(IS_PRIVATE(file_inode(file)))) |
| 1654 | return 0; | 1591 | return 0; |
| 1655 | 1592 | ||
| 1656 | isp = file_inode(file)->i_security; | 1593 | isp = smack_inode(file_inode(file)); |
| 1657 | if (isp->smk_mmap == NULL) | 1594 | if (isp->smk_mmap == NULL) |
| 1658 | return 0; | 1595 | return 0; |
| 1659 | sbsp = file_inode(file)->i_sb->s_security; | 1596 | sbsp = file_inode(file)->i_sb->s_security; |
| @@ -1662,7 +1599,7 @@ static int smack_mmap_file(struct file *file, | |||
| 1662 | return -EACCES; | 1599 | return -EACCES; |
| 1663 | mkp = isp->smk_mmap; | 1600 | mkp = isp->smk_mmap; |
| 1664 | 1601 | ||
| 1665 | tsp = current_security(); | 1602 | tsp = smack_cred(current_cred()); |
| 1666 | skp = smk_of_current(); | 1603 | skp = smk_of_current(); |
| 1667 | rc = 0; | 1604 | rc = 0; |
| 1668 | 1605 | ||
| @@ -1740,7 +1677,9 @@ static int smack_mmap_file(struct file *file, | |||
| 1740 | */ | 1677 | */ |
| 1741 | static void smack_file_set_fowner(struct file *file) | 1678 | static void smack_file_set_fowner(struct file *file) |
| 1742 | { | 1679 | { |
| 1743 | file->f_security = smk_of_current(); | 1680 | struct smack_known **blob = smack_file(file); |
| 1681 | |||
| 1682 | *blob = smk_of_current(); | ||
| 1744 | } | 1683 | } |
| 1745 | 1684 | ||
| 1746 | /** | 1685 | /** |
| @@ -1757,8 +1696,9 @@ static void smack_file_set_fowner(struct file *file) | |||
| 1757 | static int smack_file_send_sigiotask(struct task_struct *tsk, | 1696 | static int smack_file_send_sigiotask(struct task_struct *tsk, |
| 1758 | struct fown_struct *fown, int signum) | 1697 | struct fown_struct *fown, int signum) |
| 1759 | { | 1698 | { |
| 1699 | struct smack_known **blob; | ||
| 1760 | struct smack_known *skp; | 1700 | struct smack_known *skp; |
| 1761 | struct smack_known *tkp = smk_of_task(tsk->cred->security); | 1701 | struct smack_known *tkp = smk_of_task(smack_cred(tsk->cred)); |
| 1762 | const struct cred *tcred; | 1702 | const struct cred *tcred; |
| 1763 | struct file *file; | 1703 | struct file *file; |
| 1764 | int rc; | 1704 | int rc; |
| @@ -1770,7 +1710,8 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, | |||
| 1770 | file = container_of(fown, struct file, f_owner); | 1710 | file = container_of(fown, struct file, f_owner); |
| 1771 | 1711 | ||
| 1772 | /* we don't log here as rc can be overriden */ | 1712 | /* we don't log here as rc can be overriden */ |
| 1773 | skp = file->f_security; | 1713 | blob = smack_file(file); |
| 1714 | skp = *blob; | ||
| 1774 | rc = smk_access(skp, tkp, MAY_DELIVER, NULL); | 1715 | rc = smk_access(skp, tkp, MAY_DELIVER, NULL); |
| 1775 | rc = smk_bu_note("sigiotask", skp, tkp, MAY_DELIVER, rc); | 1716 | rc = smk_bu_note("sigiotask", skp, tkp, MAY_DELIVER, rc); |
| 1776 | 1717 | ||
| @@ -1811,7 +1752,7 @@ static int smack_file_receive(struct file *file) | |||
| 1811 | if (inode->i_sb->s_magic == SOCKFS_MAGIC) { | 1752 | if (inode->i_sb->s_magic == SOCKFS_MAGIC) { |
| 1812 | sock = SOCKET_I(inode); | 1753 | sock = SOCKET_I(inode); |
| 1813 | ssp = sock->sk->sk_security; | 1754 | ssp = sock->sk->sk_security; |
| 1814 | tsp = current_security(); | 1755 | tsp = smack_cred(current_cred()); |
| 1815 | /* | 1756 | /* |
| 1816 | * If the receiving process can't write to the | 1757 | * If the receiving process can't write to the |
| 1817 | * passed socket or if the passed socket can't | 1758 | * passed socket or if the passed socket can't |
| @@ -1853,7 +1794,7 @@ static int smack_file_receive(struct file *file) | |||
| 1853 | */ | 1794 | */ |
| 1854 | static int smack_file_open(struct file *file) | 1795 | static int smack_file_open(struct file *file) |
| 1855 | { | 1796 | { |
| 1856 | struct task_smack *tsp = file->f_cred->security; | 1797 | struct task_smack *tsp = smack_cred(file->f_cred); |
| 1857 | struct inode *inode = file_inode(file); | 1798 | struct inode *inode = file_inode(file); |
| 1858 | struct smk_audit_info ad; | 1799 | struct smk_audit_info ad; |
| 1859 | int rc; | 1800 | int rc; |
| @@ -1881,14 +1822,7 @@ static int smack_file_open(struct file *file) | |||
| 1881 | */ | 1822 | */ |
| 1882 | static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) | 1823 | static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) |
| 1883 | { | 1824 | { |
| 1884 | struct task_smack *tsp; | 1825 | init_task_smack(smack_cred(cred), NULL, NULL); |
| 1885 | |||
| 1886 | tsp = new_task_smack(NULL, NULL, gfp); | ||
| 1887 | if (tsp == NULL) | ||
| 1888 | return -ENOMEM; | ||
| 1889 | |||
| 1890 | cred->security = tsp; | ||
| 1891 | |||
| 1892 | return 0; | 1826 | return 0; |
| 1893 | } | 1827 | } |
| 1894 | 1828 | ||
| @@ -1900,15 +1834,11 @@ static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) | |||
| 1900 | */ | 1834 | */ |
| 1901 | static void smack_cred_free(struct cred *cred) | 1835 | static void smack_cred_free(struct cred *cred) |
| 1902 | { | 1836 | { |
| 1903 | struct task_smack *tsp = cred->security; | 1837 | struct task_smack *tsp = smack_cred(cred); |
| 1904 | struct smack_rule *rp; | 1838 | struct smack_rule *rp; |
| 1905 | struct list_head *l; | 1839 | struct list_head *l; |
| 1906 | struct list_head *n; | 1840 | struct list_head *n; |
| 1907 | 1841 | ||
| 1908 | if (tsp == NULL) | ||
| 1909 | return; | ||
| 1910 | cred->security = NULL; | ||
| 1911 | |||
| 1912 | smk_destroy_label_list(&tsp->smk_relabel); | 1842 | smk_destroy_label_list(&tsp->smk_relabel); |
| 1913 | 1843 | ||
| 1914 | list_for_each_safe(l, n, &tsp->smk_rules) { | 1844 | list_for_each_safe(l, n, &tsp->smk_rules) { |
| @@ -1916,7 +1846,6 @@ static void smack_cred_free(struct cred *cred) | |||
| 1916 | list_del(&rp->list); | 1846 | list_del(&rp->list); |
| 1917 | kfree(rp); | 1847 | kfree(rp); |
| 1918 | } | 1848 | } |
| 1919 | kfree(tsp); | ||
| 1920 | } | 1849 | } |
| 1921 | 1850 | ||
| 1922 | /** | 1851 | /** |
| @@ -1930,15 +1859,11 @@ static void smack_cred_free(struct cred *cred) | |||
| 1930 | static int smack_cred_prepare(struct cred *new, const struct cred *old, | 1859 | static int smack_cred_prepare(struct cred *new, const struct cred *old, |
| 1931 | gfp_t gfp) | 1860 | gfp_t gfp) |
| 1932 | { | 1861 | { |
| 1933 | struct task_smack *old_tsp = old->security; | 1862 | struct task_smack *old_tsp = smack_cred(old); |
| 1934 | struct task_smack *new_tsp; | 1863 | struct task_smack *new_tsp = smack_cred(new); |
| 1935 | int rc; | 1864 | int rc; |
| 1936 | 1865 | ||
| 1937 | new_tsp = new_task_smack(old_tsp->smk_task, old_tsp->smk_task, gfp); | 1866 | init_task_smack(new_tsp, old_tsp->smk_task, old_tsp->smk_task); |
| 1938 | if (new_tsp == NULL) | ||
| 1939 | return -ENOMEM; | ||
| 1940 | |||
| 1941 | new->security = new_tsp; | ||
| 1942 | 1867 | ||
| 1943 | rc = smk_copy_rules(&new_tsp->smk_rules, &old_tsp->smk_rules, gfp); | 1868 | rc = smk_copy_rules(&new_tsp->smk_rules, &old_tsp->smk_rules, gfp); |
| 1944 | if (rc != 0) | 1869 | if (rc != 0) |
| @@ -1946,10 +1871,7 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old, | |||
| 1946 | 1871 | ||
| 1947 | rc = smk_copy_relabel(&new_tsp->smk_relabel, &old_tsp->smk_relabel, | 1872 | rc = smk_copy_relabel(&new_tsp->smk_relabel, &old_tsp->smk_relabel, |
| 1948 | gfp); | 1873 | gfp); |
| 1949 | if (rc != 0) | 1874 | return rc; |
| 1950 | return rc; | ||
| 1951 | |||
| 1952 | return 0; | ||
| 1953 | } | 1875 | } |
| 1954 | 1876 | ||
| 1955 | /** | 1877 | /** |
| @@ -1961,15 +1883,14 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old, | |||
| 1961 | */ | 1883 | */ |
| 1962 | static void smack_cred_transfer(struct cred *new, const struct cred *old) | 1884 | static void smack_cred_transfer(struct cred *new, const struct cred *old) |
| 1963 | { | 1885 | { |
| 1964 | struct task_smack *old_tsp = old->security; | 1886 | struct task_smack *old_tsp = smack_cred(old); |
| 1965 | struct task_smack *new_tsp = new->security; | 1887 | struct task_smack *new_tsp = smack_cred(new); |
| 1966 | 1888 | ||
| 1967 | new_tsp->smk_task = old_tsp->smk_task; | 1889 | new_tsp->smk_task = old_tsp->smk_task; |
| 1968 | new_tsp->smk_forked = old_tsp->smk_task; | 1890 | new_tsp->smk_forked = old_tsp->smk_task; |
| 1969 | mutex_init(&new_tsp->smk_rules_lock); | 1891 | mutex_init(&new_tsp->smk_rules_lock); |
| 1970 | INIT_LIST_HEAD(&new_tsp->smk_rules); | 1892 | INIT_LIST_HEAD(&new_tsp->smk_rules); |
| 1971 | 1893 | ||
| 1972 | |||
| 1973 | /* cbs copy rule list */ | 1894 | /* cbs copy rule list */ |
| 1974 | } | 1895 | } |
| 1975 | 1896 | ||
| @@ -1980,12 +1901,12 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old) | |||
| 1980 | * | 1901 | * |
| 1981 | * Sets the secid to contain a u32 version of the smack label. | 1902 | * Sets the secid to contain a u32 version of the smack label. |
| 1982 | */ | 1903 | */ |
| 1983 | static void smack_cred_getsecid(const struct cred *c, u32 *secid) | 1904 | static void smack_cred_getsecid(const struct cred *cred, u32 *secid) |
| 1984 | { | 1905 | { |
| 1985 | struct smack_known *skp; | 1906 | struct smack_known *skp; |
| 1986 | 1907 | ||
| 1987 | rcu_read_lock(); | 1908 | rcu_read_lock(); |
| 1988 | skp = smk_of_task(c->security); | 1909 | skp = smk_of_task(smack_cred(cred)); |
| 1989 | *secid = skp->smk_secid; | 1910 | *secid = skp->smk_secid; |
| 1990 | rcu_read_unlock(); | 1911 | rcu_read_unlock(); |
| 1991 | } | 1912 | } |
| @@ -1999,7 +1920,7 @@ static void smack_cred_getsecid(const struct cred *c, u32 *secid) | |||
| 1999 | */ | 1920 | */ |
| 2000 | static int smack_kernel_act_as(struct cred *new, u32 secid) | 1921 | static int smack_kernel_act_as(struct cred *new, u32 secid) |
| 2001 | { | 1922 | { |
| 2002 | struct task_smack *new_tsp = new->security; | 1923 | struct task_smack *new_tsp = smack_cred(new); |
| 2003 | 1924 | ||
| 2004 | new_tsp->smk_task = smack_from_secid(secid); | 1925 | new_tsp->smk_task = smack_from_secid(secid); |
| 2005 | return 0; | 1926 | return 0; |
| @@ -2016,8 +1937,8 @@ static int smack_kernel_act_as(struct cred *new, u32 secid) | |||
| 2016 | static int smack_kernel_create_files_as(struct cred *new, | 1937 | static int smack_kernel_create_files_as(struct cred *new, |
| 2017 | struct inode *inode) | 1938 | struct inode *inode) |
| 2018 | { | 1939 | { |
| 2019 | struct inode_smack *isp = inode->i_security; | 1940 | struct inode_smack *isp = smack_inode(inode); |
| 2020 | struct task_smack *tsp = new->security; | 1941 | struct task_smack *tsp = smack_cred(new); |
| 2021 | 1942 | ||
| 2022 | tsp->smk_forked = isp->smk_inode; | 1943 | tsp->smk_forked = isp->smk_inode; |
| 2023 | tsp->smk_task = tsp->smk_forked; | 1944 | tsp->smk_task = tsp->smk_forked; |
| @@ -2201,7 +2122,7 @@ static int smack_task_kill(struct task_struct *p, struct kernel_siginfo *info, | |||
| 2201 | * specific behavior. This is not clean. For one thing | 2122 | * specific behavior. This is not clean. For one thing |
| 2202 | * we can't take privilege into account. | 2123 | * we can't take privilege into account. |
| 2203 | */ | 2124 | */ |
| 2204 | skp = smk_of_task(cred->security); | 2125 | skp = smk_of_task(smack_cred(cred)); |
| 2205 | rc = smk_access(skp, tkp, MAY_DELIVER, &ad); | 2126 | rc = smk_access(skp, tkp, MAY_DELIVER, &ad); |
| 2206 | rc = smk_bu_note("USB signal", skp, tkp, MAY_DELIVER, rc); | 2127 | rc = smk_bu_note("USB signal", skp, tkp, MAY_DELIVER, rc); |
| 2207 | return rc; | 2128 | return rc; |
| @@ -2216,7 +2137,7 @@ static int smack_task_kill(struct task_struct *p, struct kernel_siginfo *info, | |||
| 2216 | */ | 2137 | */ |
| 2217 | static void smack_task_to_inode(struct task_struct *p, struct inode *inode) | 2138 | static void smack_task_to_inode(struct task_struct *p, struct inode *inode) |
| 2218 | { | 2139 | { |
| 2219 | struct inode_smack *isp = inode->i_security; | 2140 | struct inode_smack *isp = smack_inode(inode); |
| 2220 | struct smack_known *skp = smk_of_task_struct(p); | 2141 | struct smack_known *skp = smk_of_task_struct(p); |
| 2221 | 2142 | ||
| 2222 | isp->smk_inode = skp; | 2143 | isp->smk_inode = skp; |
| @@ -2679,7 +2600,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, | |||
| 2679 | const void *value, size_t size, int flags) | 2600 | const void *value, size_t size, int flags) |
| 2680 | { | 2601 | { |
| 2681 | struct smack_known *skp; | 2602 | struct smack_known *skp; |
| 2682 | struct inode_smack *nsp = inode->i_security; | 2603 | struct inode_smack *nsp = smack_inode(inode); |
| 2683 | struct socket_smack *ssp; | 2604 | struct socket_smack *ssp; |
| 2684 | struct socket *sock; | 2605 | struct socket *sock; |
| 2685 | int rc = 0; | 2606 | int rc = 0; |
| @@ -2888,24 +2809,13 @@ static int smack_flags_to_may(int flags) | |||
| 2888 | */ | 2809 | */ |
| 2889 | static int smack_msg_msg_alloc_security(struct msg_msg *msg) | 2810 | static int smack_msg_msg_alloc_security(struct msg_msg *msg) |
| 2890 | { | 2811 | { |
| 2891 | struct smack_known *skp = smk_of_current(); | 2812 | struct smack_known **blob = smack_msg_msg(msg); |
| 2892 | 2813 | ||
| 2893 | msg->security = skp; | 2814 | *blob = smk_of_current(); |
| 2894 | return 0; | 2815 | return 0; |
| 2895 | } | 2816 | } |
| 2896 | 2817 | ||
| 2897 | /** | 2818 | /** |
| 2898 | * smack_msg_msg_free_security - Clear the security blob for msg_msg | ||
| 2899 | * @msg: the object | ||
| 2900 | * | ||
| 2901 | * Clears the blob pointer | ||
| 2902 | */ | ||
| 2903 | static void smack_msg_msg_free_security(struct msg_msg *msg) | ||
| 2904 | { | ||
| 2905 | msg->security = NULL; | ||
| 2906 | } | ||
| 2907 | |||
| 2908 | /** | ||
| 2909 | * smack_of_ipc - the smack pointer for the ipc | 2819 | * smack_of_ipc - the smack pointer for the ipc |
| 2910 | * @isp: the object | 2820 | * @isp: the object |
| 2911 | * | 2821 | * |
| @@ -2913,7 +2823,9 @@ static void smack_msg_msg_free_security(struct msg_msg *msg) | |||
| 2913 | */ | 2823 | */ |
| 2914 | static struct smack_known *smack_of_ipc(struct kern_ipc_perm *isp) | 2824 | static struct smack_known *smack_of_ipc(struct kern_ipc_perm *isp) |
| 2915 | { | 2825 | { |
| 2916 | return (struct smack_known *)isp->security; | 2826 | struct smack_known **blob = smack_ipc(isp); |
| 2827 | |||
| 2828 | return *blob; | ||
| 2917 | } | 2829 | } |
| 2918 | 2830 | ||
| 2919 | /** | 2831 | /** |
| @@ -2924,24 +2836,13 @@ static struct smack_known *smack_of_ipc(struct kern_ipc_perm *isp) | |||
| 2924 | */ | 2836 | */ |
| 2925 | static int smack_ipc_alloc_security(struct kern_ipc_perm *isp) | 2837 | static int smack_ipc_alloc_security(struct kern_ipc_perm *isp) |
| 2926 | { | 2838 | { |
| 2927 | struct smack_known *skp = smk_of_current(); | 2839 | struct smack_known **blob = smack_ipc(isp); |
| 2928 | 2840 | ||
| 2929 | isp->security = skp; | 2841 | *blob = smk_of_current(); |
| 2930 | return 0; | 2842 | return 0; |
| 2931 | } | 2843 | } |
| 2932 | 2844 | ||
| 2933 | /** | 2845 | /** |
| 2934 | * smack_ipc_free_security - Clear the security blob for ipc | ||
| 2935 | * @isp: the object | ||
| 2936 | * | ||
| 2937 | * Clears the blob pointer | ||
| 2938 | */ | ||
| 2939 | static void smack_ipc_free_security(struct kern_ipc_perm *isp) | ||
| 2940 | { | ||
| 2941 | isp->security = NULL; | ||
| 2942 | } | ||
| 2943 | |||
| 2944 | /** | ||
| 2945 | * smk_curacc_shm : check if current has access on shm | 2846 | * smk_curacc_shm : check if current has access on shm |
| 2946 | * @isp : the object | 2847 | * @isp : the object |
| 2947 | * @access : access requested | 2848 | * @access : access requested |
| @@ -3238,7 +3139,8 @@ static int smack_msg_queue_msgrcv(struct kern_ipc_perm *isp, struct msg_msg *msg | |||
| 3238 | */ | 3139 | */ |
| 3239 | static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) | 3140 | static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) |
| 3240 | { | 3141 | { |
| 3241 | struct smack_known *iskp = ipp->security; | 3142 | struct smack_known **blob = smack_ipc(ipp); |
| 3143 | struct smack_known *iskp = *blob; | ||
| 3242 | int may = smack_flags_to_may(flag); | 3144 | int may = smack_flags_to_may(flag); |
| 3243 | struct smk_audit_info ad; | 3145 | struct smk_audit_info ad; |
| 3244 | int rc; | 3146 | int rc; |
| @@ -3259,7 +3161,8 @@ static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) | |||
| 3259 | */ | 3161 | */ |
| 3260 | static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid) | 3162 | static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid) |
| 3261 | { | 3163 | { |
| 3262 | struct smack_known *iskp = ipp->security; | 3164 | struct smack_known **blob = smack_ipc(ipp); |
| 3165 | struct smack_known *iskp = *blob; | ||
| 3263 | 3166 | ||
| 3264 | *secid = iskp->smk_secid; | 3167 | *secid = iskp->smk_secid; |
| 3265 | } | 3168 | } |
| @@ -3287,7 +3190,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
| 3287 | if (inode == NULL) | 3190 | if (inode == NULL) |
| 3288 | return; | 3191 | return; |
| 3289 | 3192 | ||
| 3290 | isp = inode->i_security; | 3193 | isp = smack_inode(inode); |
| 3291 | 3194 | ||
| 3292 | mutex_lock(&isp->smk_lock); | 3195 | mutex_lock(&isp->smk_lock); |
| 3293 | /* | 3196 | /* |
| @@ -3390,13 +3293,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
| 3390 | */ | 3293 | */ |
| 3391 | final = &smack_known_star; | 3294 | final = &smack_known_star; |
| 3392 | /* | 3295 | /* |
| 3393 | * Fall through. | ||
| 3394 | * | ||
| 3395 | * If a smack value has been set we want to use it, | 3296 | * If a smack value has been set we want to use it, |
| 3396 | * but since tmpfs isn't giving us the opportunity | 3297 | * but since tmpfs isn't giving us the opportunity |
| 3397 | * to set mount options simulate setting the | 3298 | * to set mount options simulate setting the |
| 3398 | * superblock default. | 3299 | * superblock default. |
| 3399 | */ | 3300 | */ |
| 3301 | /* Fall through */ | ||
| 3400 | default: | 3302 | default: |
| 3401 | /* | 3303 | /* |
| 3402 | * This isn't an understood special case. | 3304 | * This isn't an understood special case. |
| @@ -3528,7 +3430,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value) | |||
| 3528 | */ | 3430 | */ |
| 3529 | static int smack_setprocattr(const char *name, void *value, size_t size) | 3431 | static int smack_setprocattr(const char *name, void *value, size_t size) |
| 3530 | { | 3432 | { |
| 3531 | struct task_smack *tsp = current_security(); | 3433 | struct task_smack *tsp = smack_cred(current_cred()); |
| 3532 | struct cred *new; | 3434 | struct cred *new; |
| 3533 | struct smack_known *skp; | 3435 | struct smack_known *skp; |
| 3534 | struct smack_known_list_elem *sklep; | 3436 | struct smack_known_list_elem *sklep; |
| @@ -3569,7 +3471,7 @@ static int smack_setprocattr(const char *name, void *value, size_t size) | |||
| 3569 | if (new == NULL) | 3471 | if (new == NULL) |
| 3570 | return -ENOMEM; | 3472 | return -ENOMEM; |
| 3571 | 3473 | ||
| 3572 | tsp = new->security; | 3474 | tsp = smack_cred(new); |
| 3573 | tsp->smk_task = skp; | 3475 | tsp->smk_task = skp; |
| 3574 | /* | 3476 | /* |
| 3575 | * process can change its label only once | 3477 | * process can change its label only once |
| @@ -4214,7 +4116,7 @@ static void smack_inet_csk_clone(struct sock *sk, | |||
| 4214 | static int smack_key_alloc(struct key *key, const struct cred *cred, | 4116 | static int smack_key_alloc(struct key *key, const struct cred *cred, |
| 4215 | unsigned long flags) | 4117 | unsigned long flags) |
| 4216 | { | 4118 | { |
| 4217 | struct smack_known *skp = smk_of_task(cred->security); | 4119 | struct smack_known *skp = smk_of_task(smack_cred(cred)); |
| 4218 | 4120 | ||
| 4219 | key->security = skp; | 4121 | key->security = skp; |
| 4220 | return 0; | 4122 | return 0; |
| @@ -4245,7 +4147,7 @@ static int smack_key_permission(key_ref_t key_ref, | |||
| 4245 | { | 4147 | { |
| 4246 | struct key *keyp; | 4148 | struct key *keyp; |
| 4247 | struct smk_audit_info ad; | 4149 | struct smk_audit_info ad; |
| 4248 | struct smack_known *tkp = smk_of_task(cred->security); | 4150 | struct smack_known *tkp = smk_of_task(smack_cred(cred)); |
| 4249 | int request = 0; | 4151 | int request = 0; |
| 4250 | int rc; | 4152 | int rc; |
| 4251 | 4153 | ||
| @@ -4520,12 +4422,12 @@ static int smack_inode_copy_up(struct dentry *dentry, struct cred **new) | |||
| 4520 | return -ENOMEM; | 4422 | return -ENOMEM; |
| 4521 | } | 4423 | } |
| 4522 | 4424 | ||
| 4523 | tsp = new_creds->security; | 4425 | tsp = smack_cred(new_creds); |
| 4524 | 4426 | ||
| 4525 | /* | 4427 | /* |
| 4526 | * Get label from overlay inode and set it in create_sid | 4428 | * Get label from overlay inode and set it in create_sid |
| 4527 | */ | 4429 | */ |
| 4528 | isp = d_inode(dentry->d_parent)->i_security; | 4430 | isp = smack_inode(d_inode(dentry->d_parent)); |
| 4529 | skp = isp->smk_inode; | 4431 | skp = isp->smk_inode; |
| 4530 | tsp->smk_task = skp; | 4432 | tsp->smk_task = skp; |
| 4531 | *new = new_creds; | 4433 | *new = new_creds; |
| @@ -4548,8 +4450,8 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode, | |||
| 4548 | const struct cred *old, | 4450 | const struct cred *old, |
| 4549 | struct cred *new) | 4451 | struct cred *new) |
| 4550 | { | 4452 | { |
| 4551 | struct task_smack *otsp = old->security; | 4453 | struct task_smack *otsp = smack_cred(old); |
| 4552 | struct task_smack *ntsp = new->security; | 4454 | struct task_smack *ntsp = smack_cred(new); |
| 4553 | struct inode_smack *isp; | 4455 | struct inode_smack *isp; |
| 4554 | int may; | 4456 | int may; |
| 4555 | 4457 | ||
| @@ -4562,7 +4464,7 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode, | |||
| 4562 | /* | 4464 | /* |
| 4563 | * the attribute of the containing directory | 4465 | * the attribute of the containing directory |
| 4564 | */ | 4466 | */ |
| 4565 | isp = d_inode(dentry->d_parent)->i_security; | 4467 | isp = smack_inode(d_inode(dentry->d_parent)); |
| 4566 | 4468 | ||
| 4567 | if (isp->smk_flags & SMK_INODE_TRANSMUTE) { | 4469 | if (isp->smk_flags & SMK_INODE_TRANSMUTE) { |
| 4568 | rcu_read_lock(); | 4470 | rcu_read_lock(); |
| @@ -4582,6 +4484,14 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode, | |||
| 4582 | return 0; | 4484 | return 0; |
| 4583 | } | 4485 | } |
| 4584 | 4486 | ||
| 4487 | struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = { | ||
| 4488 | .lbs_cred = sizeof(struct task_smack), | ||
| 4489 | .lbs_file = sizeof(struct smack_known *), | ||
| 4490 | .lbs_inode = sizeof(struct inode_smack), | ||
| 4491 | .lbs_ipc = sizeof(struct smack_known *), | ||
| 4492 | .lbs_msg_msg = sizeof(struct smack_known *), | ||
| 4493 | }; | ||
| 4494 | |||
| 4585 | static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { | 4495 | static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { |
| 4586 | LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check), | 4496 | LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check), |
| 4587 | LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), | 4497 | LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), |
| @@ -4597,7 +4507,6 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { | |||
| 4597 | LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds), | 4507 | LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds), |
| 4598 | 4508 | ||
| 4599 | LSM_HOOK_INIT(inode_alloc_security, smack_inode_alloc_security), | 4509 | LSM_HOOK_INIT(inode_alloc_security, smack_inode_alloc_security), |
| 4600 | LSM_HOOK_INIT(inode_free_security, smack_inode_free_security), | ||
| 4601 | LSM_HOOK_INIT(inode_init_security, smack_inode_init_security), | 4510 | LSM_HOOK_INIT(inode_init_security, smack_inode_init_security), |
| 4602 | LSM_HOOK_INIT(inode_link, smack_inode_link), | 4511 | LSM_HOOK_INIT(inode_link, smack_inode_link), |
| 4603 | LSM_HOOK_INIT(inode_unlink, smack_inode_unlink), | 4512 | LSM_HOOK_INIT(inode_unlink, smack_inode_unlink), |
| @@ -4616,7 +4525,6 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { | |||
| 4616 | LSM_HOOK_INIT(inode_getsecid, smack_inode_getsecid), | 4525 | LSM_HOOK_INIT(inode_getsecid, smack_inode_getsecid), |
| 4617 | 4526 | ||
| 4618 | LSM_HOOK_INIT(file_alloc_security, smack_file_alloc_security), | 4527 | LSM_HOOK_INIT(file_alloc_security, smack_file_alloc_security), |
| 4619 | LSM_HOOK_INIT(file_free_security, smack_file_free_security), | ||
| 4620 | LSM_HOOK_INIT(file_ioctl, smack_file_ioctl), | 4528 | LSM_HOOK_INIT(file_ioctl, smack_file_ioctl), |
| 4621 | LSM_HOOK_INIT(file_lock, smack_file_lock), | 4529 | LSM_HOOK_INIT(file_lock, smack_file_lock), |
| 4622 | LSM_HOOK_INIT(file_fcntl, smack_file_fcntl), | 4530 | LSM_HOOK_INIT(file_fcntl, smack_file_fcntl), |
| @@ -4652,23 +4560,19 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { | |||
| 4652 | LSM_HOOK_INIT(ipc_getsecid, smack_ipc_getsecid), | 4560 | LSM_HOOK_INIT(ipc_getsecid, smack_ipc_getsecid), |
| 4653 | 4561 | ||
| 4654 | LSM_HOOK_INIT(msg_msg_alloc_security, smack_msg_msg_alloc_security), | 4562 | LSM_HOOK_INIT(msg_msg_alloc_security, smack_msg_msg_alloc_security), |
| 4655 | LSM_HOOK_INIT(msg_msg_free_security, smack_msg_msg_free_security), | ||
| 4656 | 4563 | ||
| 4657 | LSM_HOOK_INIT(msg_queue_alloc_security, smack_ipc_alloc_security), | 4564 | LSM_HOOK_INIT(msg_queue_alloc_security, smack_ipc_alloc_security), |
| 4658 | LSM_HOOK_INIT(msg_queue_free_security, smack_ipc_free_security), | ||
| 4659 | LSM_HOOK_INIT(msg_queue_associate, smack_msg_queue_associate), | 4565 | LSM_HOOK_INIT(msg_queue_associate, smack_msg_queue_associate), |
| 4660 | LSM_HOOK_INIT(msg_queue_msgctl, smack_msg_queue_msgctl), | 4566 | LSM_HOOK_INIT(msg_queue_msgctl, smack_msg_queue_msgctl), |
| 4661 | LSM_HOOK_INIT(msg_queue_msgsnd, smack_msg_queue_msgsnd), | 4567 | LSM_HOOK_INIT(msg_queue_msgsnd, smack_msg_queue_msgsnd), |
| 4662 | LSM_HOOK_INIT(msg_queue_msgrcv, smack_msg_queue_msgrcv), | 4568 | LSM_HOOK_INIT(msg_queue_msgrcv, smack_msg_queue_msgrcv), |
| 4663 | 4569 | ||
| 4664 | LSM_HOOK_INIT(shm_alloc_security, smack_ipc_alloc_security), | 4570 | LSM_HOOK_INIT(shm_alloc_security, smack_ipc_alloc_security), |
| 4665 | LSM_HOOK_INIT(shm_free_security, smack_ipc_free_security), | ||
| 4666 | LSM_HOOK_INIT(shm_associate, smack_shm_associate), | 4571 | LSM_HOOK_INIT(shm_associate, smack_shm_associate), |
| 4667 | LSM_HOOK_INIT(shm_shmctl, smack_shm_shmctl), | 4572 | LSM_HOOK_INIT(shm_shmctl, smack_shm_shmctl), |
| 4668 | LSM_HOOK_INIT(shm_shmat, smack_shm_shmat), | 4573 | LSM_HOOK_INIT(shm_shmat, smack_shm_shmat), |
| 4669 | 4574 | ||
| 4670 | LSM_HOOK_INIT(sem_alloc_security, smack_ipc_alloc_security), | 4575 | LSM_HOOK_INIT(sem_alloc_security, smack_ipc_alloc_security), |
| 4671 | LSM_HOOK_INIT(sem_free_security, smack_ipc_free_security), | ||
| 4672 | LSM_HOOK_INIT(sem_associate, smack_sem_associate), | 4576 | LSM_HOOK_INIT(sem_associate, smack_sem_associate), |
| 4673 | LSM_HOOK_INIT(sem_semctl, smack_sem_semctl), | 4577 | LSM_HOOK_INIT(sem_semctl, smack_sem_semctl), |
| 4674 | LSM_HOOK_INIT(sem_semop, smack_sem_semop), | 4578 | LSM_HOOK_INIT(sem_semop, smack_sem_semop), |
| @@ -4759,23 +4663,23 @@ static __init void init_smack_known_list(void) | |||
| 4759 | */ | 4663 | */ |
| 4760 | static __init int smack_init(void) | 4664 | static __init int smack_init(void) |
| 4761 | { | 4665 | { |
| 4762 | struct cred *cred; | 4666 | struct cred *cred = (struct cred *) current->cred; |
| 4763 | struct task_smack *tsp; | 4667 | struct task_smack *tsp; |
| 4764 | 4668 | ||
| 4765 | if (!security_module_enable("smack")) | ||
| 4766 | return 0; | ||
| 4767 | |||
| 4768 | smack_inode_cache = KMEM_CACHE(inode_smack, 0); | 4669 | smack_inode_cache = KMEM_CACHE(inode_smack, 0); |
| 4769 | if (!smack_inode_cache) | 4670 | if (!smack_inode_cache) |
| 4770 | return -ENOMEM; | 4671 | return -ENOMEM; |
| 4771 | 4672 | ||
| 4772 | tsp = new_task_smack(&smack_known_floor, &smack_known_floor, | 4673 | /* |
| 4773 | GFP_KERNEL); | 4674 | * Set the security state for the initial task. |
| 4774 | if (tsp == NULL) { | 4675 | */ |
| 4775 | kmem_cache_destroy(smack_inode_cache); | 4676 | tsp = smack_cred(cred); |
| 4776 | return -ENOMEM; | 4677 | init_task_smack(tsp, &smack_known_floor, &smack_known_floor); |
| 4777 | } | ||
| 4778 | 4678 | ||
| 4679 | /* | ||
| 4680 | * Register with LSM | ||
| 4681 | */ | ||
| 4682 | security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), "smack"); | ||
| 4779 | smack_enabled = 1; | 4683 | smack_enabled = 1; |
| 4780 | 4684 | ||
| 4781 | pr_info("Smack: Initializing.\n"); | 4685 | pr_info("Smack: Initializing.\n"); |
| @@ -4789,20 +4693,9 @@ static __init int smack_init(void) | |||
| 4789 | pr_info("Smack: IPv6 Netfilter enabled.\n"); | 4693 | pr_info("Smack: IPv6 Netfilter enabled.\n"); |
| 4790 | #endif | 4694 | #endif |
| 4791 | 4695 | ||
| 4792 | /* | ||
| 4793 | * Set the security state for the initial task. | ||
| 4794 | */ | ||
| 4795 | cred = (struct cred *) current->cred; | ||
| 4796 | cred->security = tsp; | ||
| 4797 | |||
| 4798 | /* initialize the smack_known_list */ | 4696 | /* initialize the smack_known_list */ |
| 4799 | init_smack_known_list(); | 4697 | init_smack_known_list(); |
| 4800 | 4698 | ||
| 4801 | /* | ||
| 4802 | * Register with LSM | ||
| 4803 | */ | ||
| 4804 | security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), "smack"); | ||
| 4805 | |||
| 4806 | return 0; | 4699 | return 0; |
| 4807 | } | 4700 | } |
| 4808 | 4701 | ||
| @@ -4812,5 +4705,7 @@ static __init int smack_init(void) | |||
| 4812 | */ | 4705 | */ |
| 4813 | DEFINE_LSM(smack) = { | 4706 | DEFINE_LSM(smack) = { |
| 4814 | .name = "smack", | 4707 | .name = "smack", |
| 4708 | .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE, | ||
| 4709 | .blobs = &smack_blob_sizes, | ||
| 4815 | .init = smack_init, | 4710 | .init = smack_init, |
| 4816 | }; | 4711 | }; |
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 06b517075ec0..faf2ea3968b3 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
| @@ -2208,14 +2208,14 @@ static const struct file_operations smk_logging_ops = { | |||
| 2208 | 2208 | ||
| 2209 | static void *load_self_seq_start(struct seq_file *s, loff_t *pos) | 2209 | static void *load_self_seq_start(struct seq_file *s, loff_t *pos) |
| 2210 | { | 2210 | { |
| 2211 | struct task_smack *tsp = current_security(); | 2211 | struct task_smack *tsp = smack_cred(current_cred()); |
| 2212 | 2212 | ||
| 2213 | return smk_seq_start(s, pos, &tsp->smk_rules); | 2213 | return smk_seq_start(s, pos, &tsp->smk_rules); |
| 2214 | } | 2214 | } |
| 2215 | 2215 | ||
| 2216 | static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos) | 2216 | static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos) |
| 2217 | { | 2217 | { |
| 2218 | struct task_smack *tsp = current_security(); | 2218 | struct task_smack *tsp = smack_cred(current_cred()); |
| 2219 | 2219 | ||
| 2220 | return smk_seq_next(s, v, pos, &tsp->smk_rules); | 2220 | return smk_seq_next(s, v, pos, &tsp->smk_rules); |
| 2221 | } | 2221 | } |
| @@ -2262,7 +2262,7 @@ static int smk_open_load_self(struct inode *inode, struct file *file) | |||
| 2262 | static ssize_t smk_write_load_self(struct file *file, const char __user *buf, | 2262 | static ssize_t smk_write_load_self(struct file *file, const char __user *buf, |
| 2263 | size_t count, loff_t *ppos) | 2263 | size_t count, loff_t *ppos) |
| 2264 | { | 2264 | { |
| 2265 | struct task_smack *tsp = current_security(); | 2265 | struct task_smack *tsp = smack_cred(current_cred()); |
| 2266 | 2266 | ||
| 2267 | return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules, | 2267 | return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules, |
| 2268 | &tsp->smk_rules_lock, SMK_FIXED24_FMT); | 2268 | &tsp->smk_rules_lock, SMK_FIXED24_FMT); |
| @@ -2414,14 +2414,14 @@ static const struct file_operations smk_load2_ops = { | |||
| 2414 | 2414 | ||
| 2415 | static void *load_self2_seq_start(struct seq_file *s, loff_t *pos) | 2415 | static void *load_self2_seq_start(struct seq_file *s, loff_t *pos) |
| 2416 | { | 2416 | { |
| 2417 | struct task_smack *tsp = current_security(); | 2417 | struct task_smack *tsp = smack_cred(current_cred()); |
| 2418 | 2418 | ||
| 2419 | return smk_seq_start(s, pos, &tsp->smk_rules); | 2419 | return smk_seq_start(s, pos, &tsp->smk_rules); |
| 2420 | } | 2420 | } |
| 2421 | 2421 | ||
| 2422 | static void *load_self2_seq_next(struct seq_file *s, void *v, loff_t *pos) | 2422 | static void *load_self2_seq_next(struct seq_file *s, void *v, loff_t *pos) |
| 2423 | { | 2423 | { |
| 2424 | struct task_smack *tsp = current_security(); | 2424 | struct task_smack *tsp = smack_cred(current_cred()); |
| 2425 | 2425 | ||
| 2426 | return smk_seq_next(s, v, pos, &tsp->smk_rules); | 2426 | return smk_seq_next(s, v, pos, &tsp->smk_rules); |
| 2427 | } | 2427 | } |
| @@ -2467,7 +2467,7 @@ static int smk_open_load_self2(struct inode *inode, struct file *file) | |||
| 2467 | static ssize_t smk_write_load_self2(struct file *file, const char __user *buf, | 2467 | static ssize_t smk_write_load_self2(struct file *file, const char __user *buf, |
| 2468 | size_t count, loff_t *ppos) | 2468 | size_t count, loff_t *ppos) |
| 2469 | { | 2469 | { |
| 2470 | struct task_smack *tsp = current_security(); | 2470 | struct task_smack *tsp = smack_cred(current_cred()); |
| 2471 | 2471 | ||
| 2472 | return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules, | 2472 | return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules, |
| 2473 | &tsp->smk_rules_lock, SMK_LONG_FMT); | 2473 | &tsp->smk_rules_lock, SMK_LONG_FMT); |
| @@ -2681,14 +2681,14 @@ static const struct file_operations smk_syslog_ops = { | |||
| 2681 | 2681 | ||
| 2682 | static void *relabel_self_seq_start(struct seq_file *s, loff_t *pos) | 2682 | static void *relabel_self_seq_start(struct seq_file *s, loff_t *pos) |
| 2683 | { | 2683 | { |
| 2684 | struct task_smack *tsp = current_security(); | 2684 | struct task_smack *tsp = smack_cred(current_cred()); |
| 2685 | 2685 | ||
| 2686 | return smk_seq_start(s, pos, &tsp->smk_relabel); | 2686 | return smk_seq_start(s, pos, &tsp->smk_relabel); |
| 2687 | } | 2687 | } |
| 2688 | 2688 | ||
| 2689 | static void *relabel_self_seq_next(struct seq_file *s, void *v, loff_t *pos) | 2689 | static void *relabel_self_seq_next(struct seq_file *s, void *v, loff_t *pos) |
| 2690 | { | 2690 | { |
| 2691 | struct task_smack *tsp = current_security(); | 2691 | struct task_smack *tsp = smack_cred(current_cred()); |
| 2692 | 2692 | ||
| 2693 | return smk_seq_next(s, v, pos, &tsp->smk_relabel); | 2693 | return smk_seq_next(s, v, pos, &tsp->smk_relabel); |
| 2694 | } | 2694 | } |
| @@ -2736,7 +2736,7 @@ static int smk_open_relabel_self(struct inode *inode, struct file *file) | |||
| 2736 | static ssize_t smk_write_relabel_self(struct file *file, const char __user *buf, | 2736 | static ssize_t smk_write_relabel_self(struct file *file, const char __user *buf, |
| 2737 | size_t count, loff_t *ppos) | 2737 | size_t count, loff_t *ppos) |
| 2738 | { | 2738 | { |
| 2739 | struct task_smack *tsp = current_security(); | 2739 | struct task_smack *tsp = smack_cred(current_cred()); |
| 2740 | char *data; | 2740 | char *data; |
| 2741 | int rc; | 2741 | int rc; |
| 2742 | LIST_HEAD(list_tmp); | 2742 | LIST_HEAD(list_tmp); |
diff --git a/security/tomoyo/audit.c b/security/tomoyo/audit.c index 479b03a7a17e..3c96e8402e94 100644 --- a/security/tomoyo/audit.c +++ b/security/tomoyo/audit.c | |||
| @@ -32,6 +32,7 @@ static char *tomoyo_print_bprm(struct linux_binprm *bprm, | |||
| 32 | int argv_count = bprm->argc; | 32 | int argv_count = bprm->argc; |
| 33 | int envp_count = bprm->envc; | 33 | int envp_count = bprm->envc; |
| 34 | bool truncated = false; | 34 | bool truncated = false; |
| 35 | |||
| 35 | if (!buffer) | 36 | if (!buffer) |
| 36 | return NULL; | 37 | return NULL; |
| 37 | len = snprintf(buffer, tomoyo_buffer_len - 1, "argv[]={ "); | 38 | len = snprintf(buffer, tomoyo_buffer_len - 1, "argv[]={ "); |
| @@ -49,6 +50,7 @@ static char *tomoyo_print_bprm(struct linux_binprm *bprm, | |||
| 49 | while (offset < PAGE_SIZE) { | 50 | while (offset < PAGE_SIZE) { |
| 50 | const char *kaddr = dump->data; | 51 | const char *kaddr = dump->data; |
| 51 | const unsigned char c = kaddr[offset++]; | 52 | const unsigned char c = kaddr[offset++]; |
| 53 | |||
| 52 | if (cp == last_start) | 54 | if (cp == last_start) |
| 53 | *cp++ = '"'; | 55 | *cp++ = '"'; |
| 54 | if (cp >= buffer + tomoyo_buffer_len - 32) { | 56 | if (cp >= buffer + tomoyo_buffer_len - 32) { |
| @@ -154,19 +156,18 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r) | |||
| 154 | char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS); | 156 | char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS); |
| 155 | int pos; | 157 | int pos; |
| 156 | u8 i; | 158 | u8 i; |
| 159 | |||
| 157 | if (!buffer) | 160 | if (!buffer) |
| 158 | return NULL; | 161 | return NULL; |
| 159 | 162 | ||
| 160 | tomoyo_convert_time(ktime_get_real_seconds(), &stamp); | 163 | tomoyo_convert_time(ktime_get_real_seconds(), &stamp); |
| 161 | 164 | ||
| 162 | pos = snprintf(buffer, tomoyo_buffer_len - 1, | 165 | pos = snprintf(buffer, tomoyo_buffer_len - 1, |
| 163 | "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s " | 166 | "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s granted=%s (global-pid=%u) task={ pid=%u ppid=%u uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u fsuid=%u fsgid=%u }", |
| 164 | "granted=%s (global-pid=%u) task={ pid=%u ppid=%u " | 167 | stamp.year, stamp.month, stamp.day, stamp.hour, |
| 165 | "uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u " | 168 | stamp.min, stamp.sec, r->profile, tomoyo_mode[r->mode], |
| 166 | "fsuid=%u fsgid=%u }", stamp.year, stamp.month, | 169 | tomoyo_yesno(r->granted), gpid, tomoyo_sys_getpid(), |
| 167 | stamp.day, stamp.hour, stamp.min, stamp.sec, r->profile, | 170 | tomoyo_sys_getppid(), |
| 168 | tomoyo_mode[r->mode], tomoyo_yesno(r->granted), gpid, | ||
| 169 | tomoyo_sys_getpid(), tomoyo_sys_getppid(), | ||
| 170 | from_kuid(&init_user_ns, current_uid()), | 171 | from_kuid(&init_user_ns, current_uid()), |
| 171 | from_kgid(&init_user_ns, current_gid()), | 172 | from_kgid(&init_user_ns, current_gid()), |
| 172 | from_kuid(&init_user_ns, current_euid()), | 173 | from_kuid(&init_user_ns, current_euid()), |
| @@ -185,6 +186,7 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r) | |||
| 185 | struct tomoyo_mini_stat *stat; | 186 | struct tomoyo_mini_stat *stat; |
| 186 | unsigned int dev; | 187 | unsigned int dev; |
| 187 | umode_t mode; | 188 | umode_t mode; |
| 189 | |||
| 188 | if (!obj->stat_valid[i]) | 190 | if (!obj->stat_valid[i]) |
| 189 | continue; | 191 | continue; |
| 190 | stat = &obj->stat[i]; | 192 | stat = &obj->stat[i]; |
| @@ -193,8 +195,8 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r) | |||
| 193 | if (i & 1) { | 195 | if (i & 1) { |
| 194 | pos += snprintf(buffer + pos, | 196 | pos += snprintf(buffer + pos, |
| 195 | tomoyo_buffer_len - 1 - pos, | 197 | tomoyo_buffer_len - 1 - pos, |
| 196 | " path%u.parent={ uid=%u gid=%u " | 198 | " path%u.parent={ uid=%u gid=%u ino=%lu perm=0%o }", |
| 197 | "ino=%lu perm=0%o }", (i >> 1) + 1, | 199 | (i >> 1) + 1, |
| 198 | from_kuid(&init_user_ns, stat->uid), | 200 | from_kuid(&init_user_ns, stat->uid), |
| 199 | from_kgid(&init_user_ns, stat->gid), | 201 | from_kgid(&init_user_ns, stat->gid), |
| 200 | (unsigned long)stat->ino, | 202 | (unsigned long)stat->ino, |
| @@ -202,8 +204,8 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r) | |||
| 202 | continue; | 204 | continue; |
| 203 | } | 205 | } |
| 204 | pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos, | 206 | pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos, |
| 205 | " path%u={ uid=%u gid=%u ino=%lu major=%u" | 207 | " path%u={ uid=%u gid=%u ino=%lu major=%u minor=%u perm=0%o type=%s", |
| 206 | " minor=%u perm=0%o type=%s", (i >> 1) + 1, | 208 | (i >> 1) + 1, |
| 207 | from_kuid(&init_user_ns, stat->uid), | 209 | from_kuid(&init_user_ns, stat->uid), |
| 208 | from_kgid(&init_user_ns, stat->gid), | 210 | from_kgid(&init_user_ns, stat->gid), |
| 209 | (unsigned long)stat->ino, | 211 | (unsigned long)stat->ino, |
| @@ -249,6 +251,7 @@ char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, | |||
| 249 | const char *symlink = NULL; | 251 | const char *symlink = NULL; |
| 250 | int pos; | 252 | int pos; |
| 251 | const char *domainname = r->domain->domainname->name; | 253 | const char *domainname = r->domain->domainname->name; |
| 254 | |||
| 252 | header = tomoyo_print_header(r); | 255 | header = tomoyo_print_header(r); |
| 253 | if (!header) | 256 | if (!header) |
| 254 | return NULL; | 257 | return NULL; |
| @@ -256,6 +259,7 @@ char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, | |||
| 256 | len += strlen(domainname) + strlen(header) + 10; | 259 | len += strlen(domainname) + strlen(header) + 10; |
| 257 | if (r->ee) { | 260 | if (r->ee) { |
| 258 | struct file *file = r->ee->bprm->file; | 261 | struct file *file = r->ee->bprm->file; |
| 262 | |||
| 259 | realpath = tomoyo_realpath_from_path(&file->f_path); | 263 | realpath = tomoyo_realpath_from_path(&file->f_path); |
| 260 | bprm_info = tomoyo_print_bprm(r->ee->bprm, &r->ee->dump); | 264 | bprm_info = tomoyo_print_bprm(r->ee->bprm, &r->ee->dump); |
| 261 | if (!realpath || !bprm_info) | 265 | if (!realpath || !bprm_info) |
| @@ -275,6 +279,7 @@ char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, | |||
| 275 | pos = snprintf(buf, len, "%s", header); | 279 | pos = snprintf(buf, len, "%s", header); |
| 276 | if (realpath) { | 280 | if (realpath) { |
| 277 | struct linux_binprm *bprm = r->ee->bprm; | 281 | struct linux_binprm *bprm = r->ee->bprm; |
| 282 | |||
| 278 | pos += snprintf(buf + pos, len - pos, | 283 | pos += snprintf(buf + pos, len - pos, |
| 279 | " exec={ realpath=\"%s\" argc=%d envc=%d %s }", | 284 | " exec={ realpath=\"%s\" argc=%d envc=%d %s }", |
| 280 | realpath, bprm->argc, bprm->envc, bprm_info); | 285 | realpath, bprm->argc, bprm->envc, bprm_info); |
| @@ -328,6 +333,7 @@ static bool tomoyo_get_audit(const struct tomoyo_policy_namespace *ns, | |||
| 328 | const u8 category = tomoyo_index2category[index] + | 333 | const u8 category = tomoyo_index2category[index] + |
| 329 | TOMOYO_MAX_MAC_INDEX; | 334 | TOMOYO_MAX_MAC_INDEX; |
| 330 | struct tomoyo_profile *p; | 335 | struct tomoyo_profile *p; |
| 336 | |||
| 331 | if (!tomoyo_policy_loaded) | 337 | if (!tomoyo_policy_loaded) |
| 332 | return false; | 338 | return false; |
| 333 | p = tomoyo_profile(ns, profile); | 339 | p = tomoyo_profile(ns, profile); |
| @@ -362,6 +368,7 @@ void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt, | |||
| 362 | char *buf; | 368 | char *buf; |
| 363 | struct tomoyo_log *entry; | 369 | struct tomoyo_log *entry; |
| 364 | bool quota_exceeded = false; | 370 | bool quota_exceeded = false; |
| 371 | |||
| 365 | if (!tomoyo_get_audit(r->domain->ns, r->profile, r->type, | 372 | if (!tomoyo_get_audit(r->domain->ns, r->profile, r->type, |
| 366 | r->matched_acl, r->granted)) | 373 | r->matched_acl, r->granted)) |
| 367 | goto out; | 374 | goto out; |
| @@ -413,6 +420,7 @@ void tomoyo_write_log(struct tomoyo_request_info *r, const char *fmt, ...) | |||
| 413 | { | 420 | { |
| 414 | va_list args; | 421 | va_list args; |
| 415 | int len; | 422 | int len; |
| 423 | |||
| 416 | va_start(args, fmt); | 424 | va_start(args, fmt); |
| 417 | len = vsnprintf((char *) &len, 1, fmt, args) + 1; | 425 | len = vsnprintf((char *) &len, 1, fmt, args) + 1; |
| 418 | va_end(args); | 426 | va_end(args); |
| @@ -431,6 +439,7 @@ void tomoyo_write_log(struct tomoyo_request_info *r, const char *fmt, ...) | |||
| 431 | void tomoyo_read_log(struct tomoyo_io_buffer *head) | 439 | void tomoyo_read_log(struct tomoyo_io_buffer *head) |
| 432 | { | 440 | { |
| 433 | struct tomoyo_log *ptr = NULL; | 441 | struct tomoyo_log *ptr = NULL; |
| 442 | |||
| 434 | if (head->r.w_pos) | 443 | if (head->r.w_pos) |
| 435 | return; | 444 | return; |
| 436 | kfree(head->read_buf); | 445 | kfree(head->read_buf); |
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index c598aa00d5e3..57988d95d33d 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
| @@ -197,6 +197,7 @@ static void tomoyo_addprintf(char *buffer, int len, const char *fmt, ...) | |||
| 197 | { | 197 | { |
| 198 | va_list args; | 198 | va_list args; |
| 199 | const int pos = strlen(buffer); | 199 | const int pos = strlen(buffer); |
| 200 | |||
| 200 | va_start(args, fmt); | 201 | va_start(args, fmt); |
| 201 | vsnprintf(buffer + pos, len - pos - 1, fmt, args); | 202 | vsnprintf(buffer + pos, len - pos - 1, fmt, args); |
| 202 | va_end(args); | 203 | va_end(args); |
| @@ -214,6 +215,7 @@ static bool tomoyo_flush(struct tomoyo_io_buffer *head) | |||
| 214 | while (head->r.w_pos) { | 215 | while (head->r.w_pos) { |
| 215 | const char *w = head->r.w[0]; | 216 | const char *w = head->r.w[0]; |
| 216 | size_t len = strlen(w); | 217 | size_t len = strlen(w); |
| 218 | |||
| 217 | if (len) { | 219 | if (len) { |
| 218 | if (len > head->read_user_buf_avail) | 220 | if (len > head->read_user_buf_avail) |
| 219 | len = head->read_user_buf_avail; | 221 | len = head->read_user_buf_avail; |
| @@ -279,6 +281,7 @@ static void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, | |||
| 279 | size_t len; | 281 | size_t len; |
| 280 | size_t pos = head->r.avail; | 282 | size_t pos = head->r.avail; |
| 281 | int size = head->readbuf_size - pos; | 283 | int size = head->readbuf_size - pos; |
| 284 | |||
| 282 | if (size <= 0) | 285 | if (size <= 0) |
| 283 | return; | 286 | return; |
| 284 | va_start(args, fmt); | 287 | va_start(args, fmt); |
| @@ -344,13 +347,14 @@ static bool tomoyo_namespace_enabled; | |||
| 344 | void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns) | 347 | void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns) |
| 345 | { | 348 | { |
| 346 | unsigned int idx; | 349 | unsigned int idx; |
| 350 | |||
| 347 | for (idx = 0; idx < TOMOYO_MAX_ACL_GROUPS; idx++) | 351 | for (idx = 0; idx < TOMOYO_MAX_ACL_GROUPS; idx++) |
| 348 | INIT_LIST_HEAD(&ns->acl_group[idx]); | 352 | INIT_LIST_HEAD(&ns->acl_group[idx]); |
| 349 | for (idx = 0; idx < TOMOYO_MAX_GROUP; idx++) | 353 | for (idx = 0; idx < TOMOYO_MAX_GROUP; idx++) |
| 350 | INIT_LIST_HEAD(&ns->group_list[idx]); | 354 | INIT_LIST_HEAD(&ns->group_list[idx]); |
| 351 | for (idx = 0; idx < TOMOYO_MAX_POLICY; idx++) | 355 | for (idx = 0; idx < TOMOYO_MAX_POLICY; idx++) |
| 352 | INIT_LIST_HEAD(&ns->policy_list[idx]); | 356 | INIT_LIST_HEAD(&ns->policy_list[idx]); |
| 353 | ns->profile_version = 20110903; | 357 | ns->profile_version = 20150505; |
| 354 | tomoyo_namespace_enabled = !list_empty(&tomoyo_namespace_list); | 358 | tomoyo_namespace_enabled = !list_empty(&tomoyo_namespace_list); |
| 355 | list_add_tail_rcu(&ns->namespace_list, &tomoyo_namespace_list); | 359 | list_add_tail_rcu(&ns->namespace_list, &tomoyo_namespace_list); |
| 356 | } | 360 | } |
| @@ -433,6 +437,7 @@ static void tomoyo_print_number_union_nospace | |||
| 433 | u8 min_type = ptr->value_type[0]; | 437 | u8 min_type = ptr->value_type[0]; |
| 434 | const u8 max_type = ptr->value_type[1]; | 438 | const u8 max_type = ptr->value_type[1]; |
| 435 | char buffer[128]; | 439 | char buffer[128]; |
| 440 | |||
| 436 | buffer[0] = '\0'; | 441 | buffer[0] = '\0'; |
| 437 | for (i = 0; i < 2; i++) { | 442 | for (i = 0; i < 2; i++) { |
| 438 | switch (min_type) { | 443 | switch (min_type) { |
| @@ -487,6 +492,7 @@ static struct tomoyo_profile *tomoyo_assign_profile | |||
| 487 | { | 492 | { |
| 488 | struct tomoyo_profile *ptr; | 493 | struct tomoyo_profile *ptr; |
| 489 | struct tomoyo_profile *entry; | 494 | struct tomoyo_profile *entry; |
| 495 | |||
| 490 | if (profile >= TOMOYO_MAX_PROFILES) | 496 | if (profile >= TOMOYO_MAX_PROFILES) |
| 491 | return NULL; | 497 | return NULL; |
| 492 | ptr = ns->profile_ptr[profile]; | 498 | ptr = ns->profile_ptr[profile]; |
| @@ -530,6 +536,7 @@ struct tomoyo_profile *tomoyo_profile(const struct tomoyo_policy_namespace *ns, | |||
| 530 | { | 536 | { |
| 531 | static struct tomoyo_profile tomoyo_null_profile; | 537 | static struct tomoyo_profile tomoyo_null_profile; |
| 532 | struct tomoyo_profile *ptr = ns->profile_ptr[profile]; | 538 | struct tomoyo_profile *ptr = ns->profile_ptr[profile]; |
| 539 | |||
| 533 | if (!ptr) | 540 | if (!ptr) |
| 534 | ptr = &tomoyo_null_profile; | 541 | ptr = &tomoyo_null_profile; |
| 535 | return ptr; | 542 | return ptr; |
| @@ -546,6 +553,7 @@ struct tomoyo_profile *tomoyo_profile(const struct tomoyo_policy_namespace *ns, | |||
| 546 | static s8 tomoyo_find_yesno(const char *string, const char *find) | 553 | static s8 tomoyo_find_yesno(const char *string, const char *find) |
| 547 | { | 554 | { |
| 548 | const char *cp = strstr(string, find); | 555 | const char *cp = strstr(string, find); |
| 556 | |||
| 549 | if (cp) { | 557 | if (cp) { |
| 550 | cp += strlen(find); | 558 | cp += strlen(find); |
| 551 | if (!strncmp(cp, "=yes", 4)) | 559 | if (!strncmp(cp, "=yes", 4)) |
| @@ -569,6 +577,7 @@ static void tomoyo_set_uint(unsigned int *i, const char *string, | |||
| 569 | const char *find) | 577 | const char *find) |
| 570 | { | 578 | { |
| 571 | const char *cp = strstr(string, find); | 579 | const char *cp = strstr(string, find); |
| 580 | |||
| 572 | if (cp) | 581 | if (cp) |
| 573 | sscanf(cp + strlen(find), "=%u", i); | 582 | sscanf(cp + strlen(find), "=%u", i); |
| 574 | } | 583 | } |
| @@ -587,6 +596,7 @@ static int tomoyo_set_mode(char *name, const char *value, | |||
| 587 | { | 596 | { |
| 588 | u8 i; | 597 | u8 i; |
| 589 | u8 config; | 598 | u8 config; |
| 599 | |||
| 590 | if (!strcmp(name, "CONFIG")) { | 600 | if (!strcmp(name, "CONFIG")) { |
| 591 | i = TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX; | 601 | i = TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX; |
| 592 | config = profile->default_config; | 602 | config = profile->default_config; |
| @@ -595,10 +605,12 @@ static int tomoyo_set_mode(char *name, const char *value, | |||
| 595 | for (i = 0; i < TOMOYO_MAX_MAC_INDEX | 605 | for (i = 0; i < TOMOYO_MAX_MAC_INDEX |
| 596 | + TOMOYO_MAX_MAC_CATEGORY_INDEX; i++) { | 606 | + TOMOYO_MAX_MAC_CATEGORY_INDEX; i++) { |
| 597 | int len = 0; | 607 | int len = 0; |
| 608 | |||
| 598 | if (i < TOMOYO_MAX_MAC_INDEX) { | 609 | if (i < TOMOYO_MAX_MAC_INDEX) { |
| 599 | const u8 c = tomoyo_index2category[i]; | 610 | const u8 c = tomoyo_index2category[i]; |
| 600 | const char *category = | 611 | const char *category = |
| 601 | tomoyo_category_keywords[c]; | 612 | tomoyo_category_keywords[c]; |
| 613 | |||
| 602 | len = strlen(category); | 614 | len = strlen(category); |
| 603 | if (strncmp(name, category, len) || | 615 | if (strncmp(name, category, len) || |
| 604 | name[len++] != ':' || name[len++] != ':') | 616 | name[len++] != ':' || name[len++] != ':') |
| @@ -618,6 +630,7 @@ static int tomoyo_set_mode(char *name, const char *value, | |||
| 618 | config = TOMOYO_CONFIG_USE_DEFAULT; | 630 | config = TOMOYO_CONFIG_USE_DEFAULT; |
| 619 | } else { | 631 | } else { |
| 620 | u8 mode; | 632 | u8 mode; |
| 633 | |||
| 621 | for (mode = 0; mode < 4; mode++) | 634 | for (mode = 0; mode < 4; mode++) |
| 622 | if (strstr(value, tomoyo_mode[mode])) | 635 | if (strstr(value, tomoyo_mode[mode])) |
| 623 | /* | 636 | /* |
| @@ -664,6 +677,7 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head) | |||
| 664 | unsigned int i; | 677 | unsigned int i; |
| 665 | char *cp; | 678 | char *cp; |
| 666 | struct tomoyo_profile *profile; | 679 | struct tomoyo_profile *profile; |
| 680 | |||
| 667 | if (sscanf(data, "PROFILE_VERSION=%u", &head->w.ns->profile_version) | 681 | if (sscanf(data, "PROFILE_VERSION=%u", &head->w.ns->profile_version) |
| 668 | == 1) | 682 | == 1) |
| 669 | return 0; | 683 | return 0; |
| @@ -683,6 +697,7 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head) | |||
| 683 | const struct tomoyo_path_info *new_comment | 697 | const struct tomoyo_path_info *new_comment |
| 684 | = tomoyo_get_name(cp); | 698 | = tomoyo_get_name(cp); |
| 685 | const struct tomoyo_path_info *old_comment; | 699 | const struct tomoyo_path_info *old_comment; |
| 700 | |||
| 686 | if (!new_comment) | 701 | if (!new_comment) |
| 687 | return -ENOMEM; | 702 | return -ENOMEM; |
| 688 | spin_lock(&lock); | 703 | spin_lock(&lock); |
| @@ -732,6 +747,7 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head) | |||
| 732 | struct tomoyo_policy_namespace *ns = | 747 | struct tomoyo_policy_namespace *ns = |
| 733 | container_of(head->r.ns, typeof(*ns), namespace_list); | 748 | container_of(head->r.ns, typeof(*ns), namespace_list); |
| 734 | const struct tomoyo_profile *profile; | 749 | const struct tomoyo_profile *profile; |
| 750 | |||
| 735 | if (head->r.eof) | 751 | if (head->r.eof) |
| 736 | return; | 752 | return; |
| 737 | next: | 753 | next: |
| @@ -760,6 +776,7 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head) | |||
| 760 | u8 i; | 776 | u8 i; |
| 761 | const struct tomoyo_path_info *comment = | 777 | const struct tomoyo_path_info *comment = |
| 762 | profile->comment; | 778 | profile->comment; |
| 779 | |||
| 763 | tomoyo_print_namespace(head); | 780 | tomoyo_print_namespace(head); |
| 764 | tomoyo_io_printf(head, "%u-COMMENT=", index); | 781 | tomoyo_io_printf(head, "%u-COMMENT=", index); |
| 765 | tomoyo_set_string(head, comment ? comment->name : ""); | 782 | tomoyo_set_string(head, comment ? comment->name : ""); |
| @@ -788,6 +805,7 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head) | |||
| 788 | + TOMOYO_MAX_MAC_CATEGORY_INDEX; head->r.bit++) { | 805 | + TOMOYO_MAX_MAC_CATEGORY_INDEX; head->r.bit++) { |
| 789 | const u8 i = head->r.bit; | 806 | const u8 i = head->r.bit; |
| 790 | const u8 config = profile->config[i]; | 807 | const u8 config = profile->config[i]; |
| 808 | |||
| 791 | if (config == TOMOYO_CONFIG_USE_DEFAULT) | 809 | if (config == TOMOYO_CONFIG_USE_DEFAULT) |
| 792 | continue; | 810 | continue; |
| 793 | tomoyo_print_namespace(head); | 811 | tomoyo_print_namespace(head); |
| @@ -847,10 +865,10 @@ static int tomoyo_update_manager_entry(const char *manager, | |||
| 847 | struct tomoyo_acl_param param = { | 865 | struct tomoyo_acl_param param = { |
| 848 | /* .ns = &tomoyo_kernel_namespace, */ | 866 | /* .ns = &tomoyo_kernel_namespace, */ |
| 849 | .is_delete = is_delete, | 867 | .is_delete = is_delete, |
| 850 | .list = &tomoyo_kernel_namespace. | 868 | .list = &tomoyo_kernel_namespace.policy_list[TOMOYO_ID_MANAGER], |
| 851 | policy_list[TOMOYO_ID_MANAGER], | ||
| 852 | }; | 869 | }; |
| 853 | int error = is_delete ? -ENOENT : -ENOMEM; | 870 | int error = is_delete ? -ENOENT : -ENOMEM; |
| 871 | |||
| 854 | if (!tomoyo_correct_domain(manager) && | 872 | if (!tomoyo_correct_domain(manager) && |
| 855 | !tomoyo_correct_word(manager)) | 873 | !tomoyo_correct_word(manager)) |
| 856 | return -EINVAL; | 874 | return -EINVAL; |
| @@ -894,10 +912,10 @@ static void tomoyo_read_manager(struct tomoyo_io_buffer *head) | |||
| 894 | { | 912 | { |
| 895 | if (head->r.eof) | 913 | if (head->r.eof) |
| 896 | return; | 914 | return; |
| 897 | list_for_each_cookie(head->r.acl, &tomoyo_kernel_namespace. | 915 | list_for_each_cookie(head->r.acl, &tomoyo_kernel_namespace.policy_list[TOMOYO_ID_MANAGER]) { |
| 898 | policy_list[TOMOYO_ID_MANAGER]) { | ||
| 899 | struct tomoyo_manager *ptr = | 916 | struct tomoyo_manager *ptr = |
| 900 | list_entry(head->r.acl, typeof(*ptr), head.list); | 917 | list_entry(head->r.acl, typeof(*ptr), head.list); |
| 918 | |||
| 901 | if (ptr->head.is_deleted) | 919 | if (ptr->head.is_deleted) |
| 902 | continue; | 920 | continue; |
| 903 | if (!tomoyo_flush(head)) | 921 | if (!tomoyo_flush(head)) |
| @@ -933,8 +951,7 @@ static bool tomoyo_manager(void) | |||
| 933 | exe = tomoyo_get_exe(); | 951 | exe = tomoyo_get_exe(); |
| 934 | if (!exe) | 952 | if (!exe) |
| 935 | return false; | 953 | return false; |
| 936 | list_for_each_entry_rcu(ptr, &tomoyo_kernel_namespace. | 954 | list_for_each_entry_rcu(ptr, &tomoyo_kernel_namespace.policy_list[TOMOYO_ID_MANAGER], head.list) { |
| 937 | policy_list[TOMOYO_ID_MANAGER], head.list) { | ||
| 938 | if (!ptr->head.is_deleted && | 955 | if (!ptr->head.is_deleted && |
| 939 | (!tomoyo_pathcmp(domainname, ptr->manager) || | 956 | (!tomoyo_pathcmp(domainname, ptr->manager) || |
| 940 | !strcmp(exe, ptr->manager->name))) { | 957 | !strcmp(exe, ptr->manager->name))) { |
| @@ -945,9 +962,10 @@ static bool tomoyo_manager(void) | |||
| 945 | if (!found) { /* Reduce error messages. */ | 962 | if (!found) { /* Reduce error messages. */ |
| 946 | static pid_t last_pid; | 963 | static pid_t last_pid; |
| 947 | const pid_t pid = current->pid; | 964 | const pid_t pid = current->pid; |
| 965 | |||
| 948 | if (last_pid != pid) { | 966 | if (last_pid != pid) { |
| 949 | printk(KERN_WARNING "%s ( %s ) is not permitted to " | 967 | pr_warn("%s ( %s ) is not permitted to update policies.\n", |
| 950 | "update policies.\n", domainname->name, exe); | 968 | domainname->name, exe); |
| 951 | last_pid = pid; | 969 | last_pid = pid; |
| 952 | } | 970 | } |
| 953 | } | 971 | } |
| @@ -974,19 +992,21 @@ static bool tomoyo_select_domain(struct tomoyo_io_buffer *head, | |||
| 974 | unsigned int pid; | 992 | unsigned int pid; |
| 975 | struct tomoyo_domain_info *domain = NULL; | 993 | struct tomoyo_domain_info *domain = NULL; |
| 976 | bool global_pid = false; | 994 | bool global_pid = false; |
| 995 | |||
| 977 | if (strncmp(data, "select ", 7)) | 996 | if (strncmp(data, "select ", 7)) |
| 978 | return false; | 997 | return false; |
| 979 | data += 7; | 998 | data += 7; |
| 980 | if (sscanf(data, "pid=%u", &pid) == 1 || | 999 | if (sscanf(data, "pid=%u", &pid) == 1 || |
| 981 | (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) { | 1000 | (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) { |
| 982 | struct task_struct *p; | 1001 | struct task_struct *p; |
| 1002 | |||
| 983 | rcu_read_lock(); | 1003 | rcu_read_lock(); |
| 984 | if (global_pid) | 1004 | if (global_pid) |
| 985 | p = find_task_by_pid_ns(pid, &init_pid_ns); | 1005 | p = find_task_by_pid_ns(pid, &init_pid_ns); |
| 986 | else | 1006 | else |
| 987 | p = find_task_by_vpid(pid); | 1007 | p = find_task_by_vpid(pid); |
| 988 | if (p) | 1008 | if (p) |
| 989 | domain = tomoyo_real_domain(p); | 1009 | domain = tomoyo_task(p)->domain_info; |
| 990 | rcu_read_unlock(); | 1010 | rcu_read_unlock(); |
| 991 | } else if (!strncmp(data, "domain=", 7)) { | 1011 | } else if (!strncmp(data, "domain=", 7)) { |
| 992 | if (tomoyo_domain_def(data + 7)) | 1012 | if (tomoyo_domain_def(data + 7)) |
| @@ -1020,10 +1040,11 @@ static bool tomoyo_select_domain(struct tomoyo_io_buffer *head, | |||
| 1020 | * Returns true if @a == @b, false otherwise. | 1040 | * Returns true if @a == @b, false otherwise. |
| 1021 | */ | 1041 | */ |
| 1022 | static bool tomoyo_same_task_acl(const struct tomoyo_acl_info *a, | 1042 | static bool tomoyo_same_task_acl(const struct tomoyo_acl_info *a, |
| 1023 | const struct tomoyo_acl_info *b) | 1043 | const struct tomoyo_acl_info *b) |
| 1024 | { | 1044 | { |
| 1025 | const struct tomoyo_task_acl *p1 = container_of(a, typeof(*p1), head); | 1045 | const struct tomoyo_task_acl *p1 = container_of(a, typeof(*p1), head); |
| 1026 | const struct tomoyo_task_acl *p2 = container_of(b, typeof(*p2), head); | 1046 | const struct tomoyo_task_acl *p2 = container_of(b, typeof(*p2), head); |
| 1047 | |||
| 1027 | return p1->domainname == p2->domainname; | 1048 | return p1->domainname == p2->domainname; |
| 1028 | } | 1049 | } |
| 1029 | 1050 | ||
| @@ -1039,11 +1060,13 @@ static bool tomoyo_same_task_acl(const struct tomoyo_acl_info *a, | |||
| 1039 | static int tomoyo_write_task(struct tomoyo_acl_param *param) | 1060 | static int tomoyo_write_task(struct tomoyo_acl_param *param) |
| 1040 | { | 1061 | { |
| 1041 | int error = -EINVAL; | 1062 | int error = -EINVAL; |
| 1063 | |||
| 1042 | if (tomoyo_str_starts(¶m->data, "manual_domain_transition ")) { | 1064 | if (tomoyo_str_starts(¶m->data, "manual_domain_transition ")) { |
| 1043 | struct tomoyo_task_acl e = { | 1065 | struct tomoyo_task_acl e = { |
| 1044 | .head.type = TOMOYO_TYPE_MANUAL_TASK_ACL, | 1066 | .head.type = TOMOYO_TYPE_MANUAL_TASK_ACL, |
| 1045 | .domainname = tomoyo_get_domainname(param), | 1067 | .domainname = tomoyo_get_domainname(param), |
| 1046 | }; | 1068 | }; |
| 1069 | |||
| 1047 | if (e.domainname) | 1070 | if (e.domainname) |
| 1048 | error = tomoyo_update_domain(&e.head, sizeof(e), param, | 1071 | error = tomoyo_update_domain(&e.head, sizeof(e), param, |
| 1049 | tomoyo_same_task_acl, | 1072 | tomoyo_same_task_acl, |
| @@ -1110,7 +1133,7 @@ static int tomoyo_write_domain2(struct tomoyo_policy_namespace *ns, | |||
| 1110 | }; | 1133 | }; |
| 1111 | static const struct { | 1134 | static const struct { |
| 1112 | const char *keyword; | 1135 | const char *keyword; |
| 1113 | int (*write) (struct tomoyo_acl_param *); | 1136 | int (*write)(struct tomoyo_acl_param *param); |
| 1114 | } tomoyo_callback[5] = { | 1137 | } tomoyo_callback[5] = { |
| 1115 | { "file ", tomoyo_write_file }, | 1138 | { "file ", tomoyo_write_file }, |
| 1116 | { "network inet ", tomoyo_write_inet_network }, | 1139 | { "network inet ", tomoyo_write_inet_network }, |
| @@ -1151,9 +1174,11 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head) | |||
| 1151 | struct tomoyo_domain_info *domain = head->w.domain; | 1174 | struct tomoyo_domain_info *domain = head->w.domain; |
| 1152 | const bool is_delete = head->w.is_delete; | 1175 | const bool is_delete = head->w.is_delete; |
| 1153 | bool is_select = !is_delete && tomoyo_str_starts(&data, "select "); | 1176 | bool is_select = !is_delete && tomoyo_str_starts(&data, "select "); |
| 1154 | unsigned int profile; | 1177 | unsigned int idx; |
| 1178 | |||
| 1155 | if (*data == '<') { | 1179 | if (*data == '<') { |
| 1156 | int ret = 0; | 1180 | int ret = 0; |
| 1181 | |||
| 1157 | domain = NULL; | 1182 | domain = NULL; |
| 1158 | if (is_delete) | 1183 | if (is_delete) |
| 1159 | ret = tomoyo_delete_domain(data); | 1184 | ret = tomoyo_delete_domain(data); |
| @@ -1167,23 +1192,27 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head) | |||
| 1167 | if (!domain) | 1192 | if (!domain) |
| 1168 | return -EINVAL; | 1193 | return -EINVAL; |
| 1169 | ns = domain->ns; | 1194 | ns = domain->ns; |
| 1170 | if (sscanf(data, "use_profile %u", &profile) == 1 | 1195 | if (sscanf(data, "use_profile %u", &idx) == 1 |
| 1171 | && profile < TOMOYO_MAX_PROFILES) { | 1196 | && idx < TOMOYO_MAX_PROFILES) { |
| 1172 | if (!tomoyo_policy_loaded || ns->profile_ptr[profile]) | 1197 | if (!tomoyo_policy_loaded || ns->profile_ptr[idx]) |
| 1173 | domain->profile = (u8) profile; | 1198 | if (!is_delete) |
| 1199 | domain->profile = (u8) idx; | ||
| 1174 | return 0; | 1200 | return 0; |
| 1175 | } | 1201 | } |
| 1176 | if (sscanf(data, "use_group %u\n", &profile) == 1 | 1202 | if (sscanf(data, "use_group %u\n", &idx) == 1 |
| 1177 | && profile < TOMOYO_MAX_ACL_GROUPS) { | 1203 | && idx < TOMOYO_MAX_ACL_GROUPS) { |
| 1178 | if (!is_delete) | 1204 | if (!is_delete) |
| 1179 | domain->group = (u8) profile; | 1205 | set_bit(idx, domain->group); |
| 1206 | else | ||
| 1207 | clear_bit(idx, domain->group); | ||
| 1180 | return 0; | 1208 | return 0; |
| 1181 | } | 1209 | } |
| 1182 | for (profile = 0; profile < TOMOYO_MAX_DOMAIN_INFO_FLAGS; profile++) { | 1210 | for (idx = 0; idx < TOMOYO_MAX_DOMAIN_INFO_FLAGS; idx++) { |
| 1183 | const char *cp = tomoyo_dif[profile]; | 1211 | const char *cp = tomoyo_dif[idx]; |
| 1212 | |||
| 1184 | if (strncmp(data, cp, strlen(cp) - 1)) | 1213 | if (strncmp(data, cp, strlen(cp) - 1)) |
| 1185 | continue; | 1214 | continue; |
| 1186 | domain->flags[profile] = !is_delete; | 1215 | domain->flags[idx] = !is_delete; |
| 1187 | return 0; | 1216 | return 0; |
| 1188 | } | 1217 | } |
| 1189 | return tomoyo_write_domain2(ns, &domain->acl_info_list, data, | 1218 | return tomoyo_write_domain2(ns, &domain->acl_info_list, data, |
| @@ -1225,9 +1254,11 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head, | |||
| 1225 | const struct tomoyo_envp *envp = | 1254 | const struct tomoyo_envp *envp = |
| 1226 | (typeof(envp)) (argv + cond->argc); | 1255 | (typeof(envp)) (argv + cond->argc); |
| 1227 | u16 skip; | 1256 | u16 skip; |
| 1257 | |||
| 1228 | for (skip = 0; skip < head->r.cond_index; skip++) { | 1258 | for (skip = 0; skip < head->r.cond_index; skip++) { |
| 1229 | const u8 left = condp->left; | 1259 | const u8 left = condp->left; |
| 1230 | const u8 right = condp->right; | 1260 | const u8 right = condp->right; |
| 1261 | |||
| 1231 | condp++; | 1262 | condp++; |
| 1232 | switch (left) { | 1263 | switch (left) { |
| 1233 | case TOMOYO_ARGV_ENTRY: | 1264 | case TOMOYO_ARGV_ENTRY: |
| @@ -1253,6 +1284,7 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head, | |||
| 1253 | const u8 match = condp->equals; | 1284 | const u8 match = condp->equals; |
| 1254 | const u8 left = condp->left; | 1285 | const u8 left = condp->left; |
| 1255 | const u8 right = condp->right; | 1286 | const u8 right = condp->right; |
| 1287 | |||
| 1256 | if (!tomoyo_flush(head)) | 1288 | if (!tomoyo_flush(head)) |
| 1257 | return false; | 1289 | return false; |
| 1258 | condp++; | 1290 | condp++; |
| @@ -1262,8 +1294,7 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head, | |||
| 1262 | case TOMOYO_ARGV_ENTRY: | 1294 | case TOMOYO_ARGV_ENTRY: |
| 1263 | tomoyo_io_printf(head, | 1295 | tomoyo_io_printf(head, |
| 1264 | "exec.argv[%lu]%s=\"", | 1296 | "exec.argv[%lu]%s=\"", |
| 1265 | argv->index, argv-> | 1297 | argv->index, argv->is_not ? "!" : ""); |
| 1266 | is_not ? "!" : ""); | ||
| 1267 | tomoyo_set_string(head, | 1298 | tomoyo_set_string(head, |
| 1268 | argv->value->name); | 1299 | argv->value->name); |
| 1269 | tomoyo_set_string(head, "\""); | 1300 | tomoyo_set_string(head, "\""); |
| @@ -1274,12 +1305,10 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head, | |||
| 1274 | "exec.envp[\""); | 1305 | "exec.envp[\""); |
| 1275 | tomoyo_set_string(head, | 1306 | tomoyo_set_string(head, |
| 1276 | envp->name->name); | 1307 | envp->name->name); |
| 1277 | tomoyo_io_printf(head, "\"]%s=", envp-> | 1308 | tomoyo_io_printf(head, "\"]%s=", envp->is_not ? "!" : ""); |
| 1278 | is_not ? "!" : ""); | ||
| 1279 | if (envp->value) { | 1309 | if (envp->value) { |
| 1280 | tomoyo_set_string(head, "\""); | 1310 | tomoyo_set_string(head, "\""); |
| 1281 | tomoyo_set_string(head, envp-> | 1311 | tomoyo_set_string(head, envp->value->name); |
| 1282 | value->name); | ||
| 1283 | tomoyo_set_string(head, "\""); | 1312 | tomoyo_set_string(head, "\""); |
| 1284 | } else { | 1313 | } else { |
| 1285 | tomoyo_set_string(head, | 1314 | tomoyo_set_string(head, |
| @@ -1375,6 +1404,7 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | |||
| 1375 | struct tomoyo_path_acl *ptr = | 1404 | struct tomoyo_path_acl *ptr = |
| 1376 | container_of(acl, typeof(*ptr), head); | 1405 | container_of(acl, typeof(*ptr), head); |
| 1377 | const u16 perm = ptr->perm; | 1406 | const u16 perm = ptr->perm; |
| 1407 | |||
| 1378 | for (bit = 0; bit < TOMOYO_MAX_PATH_OPERATION; bit++) { | 1408 | for (bit = 0; bit < TOMOYO_MAX_PATH_OPERATION; bit++) { |
| 1379 | if (!(perm & (1 << bit))) | 1409 | if (!(perm & (1 << bit))) |
| 1380 | continue; | 1410 | continue; |
| @@ -1395,6 +1425,7 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | |||
| 1395 | } else if (acl_type == TOMOYO_TYPE_MANUAL_TASK_ACL) { | 1425 | } else if (acl_type == TOMOYO_TYPE_MANUAL_TASK_ACL) { |
| 1396 | struct tomoyo_task_acl *ptr = | 1426 | struct tomoyo_task_acl *ptr = |
| 1397 | container_of(acl, typeof(*ptr), head); | 1427 | container_of(acl, typeof(*ptr), head); |
| 1428 | |||
| 1398 | tomoyo_set_group(head, "task "); | 1429 | tomoyo_set_group(head, "task "); |
| 1399 | tomoyo_set_string(head, "manual_domain_transition "); | 1430 | tomoyo_set_string(head, "manual_domain_transition "); |
| 1400 | tomoyo_set_string(head, ptr->domainname->name); | 1431 | tomoyo_set_string(head, ptr->domainname->name); |
| @@ -1404,6 +1435,7 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | |||
| 1404 | struct tomoyo_path2_acl *ptr = | 1435 | struct tomoyo_path2_acl *ptr = |
| 1405 | container_of(acl, typeof(*ptr), head); | 1436 | container_of(acl, typeof(*ptr), head); |
| 1406 | const u8 perm = ptr->perm; | 1437 | const u8 perm = ptr->perm; |
| 1438 | |||
| 1407 | for (bit = 0; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) { | 1439 | for (bit = 0; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) { |
| 1408 | if (!(perm & (1 << bit))) | 1440 | if (!(perm & (1 << bit))) |
| 1409 | continue; | 1441 | continue; |
| @@ -1424,6 +1456,7 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | |||
| 1424 | struct tomoyo_path_number_acl *ptr = | 1456 | struct tomoyo_path_number_acl *ptr = |
| 1425 | container_of(acl, typeof(*ptr), head); | 1457 | container_of(acl, typeof(*ptr), head); |
| 1426 | const u8 perm = ptr->perm; | 1458 | const u8 perm = ptr->perm; |
| 1459 | |||
| 1427 | for (bit = 0; bit < TOMOYO_MAX_PATH_NUMBER_OPERATION; bit++) { | 1460 | for (bit = 0; bit < TOMOYO_MAX_PATH_NUMBER_OPERATION; bit++) { |
| 1428 | if (!(perm & (1 << bit))) | 1461 | if (!(perm & (1 << bit))) |
| 1429 | continue; | 1462 | continue; |
| @@ -1444,6 +1477,7 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | |||
| 1444 | struct tomoyo_mkdev_acl *ptr = | 1477 | struct tomoyo_mkdev_acl *ptr = |
| 1445 | container_of(acl, typeof(*ptr), head); | 1478 | container_of(acl, typeof(*ptr), head); |
| 1446 | const u8 perm = ptr->perm; | 1479 | const u8 perm = ptr->perm; |
| 1480 | |||
| 1447 | for (bit = 0; bit < TOMOYO_MAX_MKDEV_OPERATION; bit++) { | 1481 | for (bit = 0; bit < TOMOYO_MAX_MKDEV_OPERATION; bit++) { |
| 1448 | if (!(perm & (1 << bit))) | 1482 | if (!(perm & (1 << bit))) |
| 1449 | continue; | 1483 | continue; |
| @@ -1490,6 +1524,7 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | |||
| 1490 | ->name); | 1524 | ->name); |
| 1491 | } else { | 1525 | } else { |
| 1492 | char buf[128]; | 1526 | char buf[128]; |
| 1527 | |||
| 1493 | tomoyo_print_ip(buf, sizeof(buf), &ptr->address); | 1528 | tomoyo_print_ip(buf, sizeof(buf), &ptr->address); |
| 1494 | tomoyo_io_printf(head, "%s", buf); | 1529 | tomoyo_io_printf(head, "%s", buf); |
| 1495 | } | 1530 | } |
| @@ -1519,6 +1554,7 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | |||
| 1519 | } else if (acl_type == TOMOYO_TYPE_MOUNT_ACL) { | 1554 | } else if (acl_type == TOMOYO_TYPE_MOUNT_ACL) { |
| 1520 | struct tomoyo_mount_acl *ptr = | 1555 | struct tomoyo_mount_acl *ptr = |
| 1521 | container_of(acl, typeof(*ptr), head); | 1556 | container_of(acl, typeof(*ptr), head); |
| 1557 | |||
| 1522 | tomoyo_set_group(head, "file mount"); | 1558 | tomoyo_set_group(head, "file mount"); |
| 1523 | tomoyo_print_name_union(head, &ptr->dev_name); | 1559 | tomoyo_print_name_union(head, &ptr->dev_name); |
| 1524 | tomoyo_print_name_union(head, &ptr->dir_name); | 1560 | tomoyo_print_name_union(head, &ptr->dir_name); |
| @@ -1562,6 +1598,7 @@ static bool tomoyo_read_domain2(struct tomoyo_io_buffer *head, | |||
| 1562 | list_for_each_cookie(head->r.acl, list) { | 1598 | list_for_each_cookie(head->r.acl, list) { |
| 1563 | struct tomoyo_acl_info *ptr = | 1599 | struct tomoyo_acl_info *ptr = |
| 1564 | list_entry(head->r.acl, typeof(*ptr), list); | 1600 | list_entry(head->r.acl, typeof(*ptr), list); |
| 1601 | |||
| 1565 | if (!tomoyo_print_entry(head, ptr)) | 1602 | if (!tomoyo_print_entry(head, ptr)) |
| 1566 | return false; | 1603 | return false; |
| 1567 | } | 1604 | } |
| @@ -1583,8 +1620,9 @@ static void tomoyo_read_domain(struct tomoyo_io_buffer *head) | |||
| 1583 | list_for_each_cookie(head->r.domain, &tomoyo_domain_list) { | 1620 | list_for_each_cookie(head->r.domain, &tomoyo_domain_list) { |
| 1584 | struct tomoyo_domain_info *domain = | 1621 | struct tomoyo_domain_info *domain = |
| 1585 | list_entry(head->r.domain, typeof(*domain), list); | 1622 | list_entry(head->r.domain, typeof(*domain), list); |
| 1623 | u8 i; | ||
| 1624 | |||
| 1586 | switch (head->r.step) { | 1625 | switch (head->r.step) { |
| 1587 | u8 i; | ||
| 1588 | case 0: | 1626 | case 0: |
| 1589 | if (domain->is_deleted && | 1627 | if (domain->is_deleted && |
| 1590 | !head->r.print_this_domain_only) | 1628 | !head->r.print_this_domain_only) |
| @@ -1594,22 +1632,33 @@ static void tomoyo_read_domain(struct tomoyo_io_buffer *head) | |||
| 1594 | tomoyo_set_lf(head); | 1632 | tomoyo_set_lf(head); |
| 1595 | tomoyo_io_printf(head, "use_profile %u\n", | 1633 | tomoyo_io_printf(head, "use_profile %u\n", |
| 1596 | domain->profile); | 1634 | domain->profile); |
| 1597 | tomoyo_io_printf(head, "use_group %u\n", | ||
| 1598 | domain->group); | ||
| 1599 | for (i = 0; i < TOMOYO_MAX_DOMAIN_INFO_FLAGS; i++) | 1635 | for (i = 0; i < TOMOYO_MAX_DOMAIN_INFO_FLAGS; i++) |
| 1600 | if (domain->flags[i]) | 1636 | if (domain->flags[i]) |
| 1601 | tomoyo_set_string(head, tomoyo_dif[i]); | 1637 | tomoyo_set_string(head, tomoyo_dif[i]); |
| 1638 | head->r.index = 0; | ||
| 1602 | head->r.step++; | 1639 | head->r.step++; |
| 1603 | tomoyo_set_lf(head); | ||
| 1604 | /* fall through */ | 1640 | /* fall through */ |
| 1605 | case 1: | 1641 | case 1: |
| 1642 | while (head->r.index < TOMOYO_MAX_ACL_GROUPS) { | ||
| 1643 | i = head->r.index++; | ||
| 1644 | if (!test_bit(i, domain->group)) | ||
| 1645 | continue; | ||
| 1646 | tomoyo_io_printf(head, "use_group %u\n", i); | ||
| 1647 | if (!tomoyo_flush(head)) | ||
| 1648 | return; | ||
| 1649 | } | ||
| 1650 | head->r.index = 0; | ||
| 1651 | head->r.step++; | ||
| 1652 | tomoyo_set_lf(head); | ||
| 1653 | /* fall through */ | ||
| 1654 | case 2: | ||
| 1606 | if (!tomoyo_read_domain2(head, &domain->acl_info_list)) | 1655 | if (!tomoyo_read_domain2(head, &domain->acl_info_list)) |
| 1607 | return; | 1656 | return; |
| 1608 | head->r.step++; | 1657 | head->r.step++; |
| 1609 | if (!tomoyo_set_lf(head)) | 1658 | if (!tomoyo_set_lf(head)) |
| 1610 | return; | 1659 | return; |
| 1611 | /* fall through */ | 1660 | /* fall through */ |
| 1612 | case 2: | 1661 | case 3: |
| 1613 | head->r.step = 0; | 1662 | head->r.step = 0; |
| 1614 | if (head->r.print_this_domain_only) | 1663 | if (head->r.print_this_domain_only) |
| 1615 | goto done; | 1664 | goto done; |
| @@ -1668,7 +1717,7 @@ static void tomoyo_read_pid(struct tomoyo_io_buffer *head) | |||
| 1668 | else | 1717 | else |
| 1669 | p = find_task_by_vpid(pid); | 1718 | p = find_task_by_vpid(pid); |
| 1670 | if (p) | 1719 | if (p) |
| 1671 | domain = tomoyo_real_domain(p); | 1720 | domain = tomoyo_task(p)->domain_info; |
| 1672 | rcu_read_unlock(); | 1721 | rcu_read_unlock(); |
| 1673 | if (!domain) | 1722 | if (!domain) |
| 1674 | return; | 1723 | return; |
| @@ -1711,6 +1760,7 @@ static int tomoyo_write_exception(struct tomoyo_io_buffer *head) | |||
| 1711 | .data = head->write_buf, | 1760 | .data = head->write_buf, |
| 1712 | }; | 1761 | }; |
| 1713 | u8 i; | 1762 | u8 i; |
| 1763 | |||
| 1714 | if (tomoyo_str_starts(¶m.data, "aggregator ")) | 1764 | if (tomoyo_str_starts(¶m.data, "aggregator ")) |
| 1715 | return tomoyo_write_aggregator(¶m); | 1765 | return tomoyo_write_aggregator(¶m); |
| 1716 | for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++) | 1766 | for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++) |
| @@ -1722,6 +1772,7 @@ static int tomoyo_write_exception(struct tomoyo_io_buffer *head) | |||
| 1722 | if (tomoyo_str_starts(¶m.data, "acl_group ")) { | 1772 | if (tomoyo_str_starts(¶m.data, "acl_group ")) { |
| 1723 | unsigned int group; | 1773 | unsigned int group; |
| 1724 | char *data; | 1774 | char *data; |
| 1775 | |||
| 1725 | group = simple_strtoul(param.data, &data, 10); | 1776 | group = simple_strtoul(param.data, &data, 10); |
| 1726 | if (group < TOMOYO_MAX_ACL_GROUPS && *data++ == ' ') | 1777 | if (group < TOMOYO_MAX_ACL_GROUPS && *data++ == ' ') |
| 1727 | return tomoyo_write_domain2 | 1778 | return tomoyo_write_domain2 |
| @@ -1746,12 +1797,15 @@ static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx) | |||
| 1746 | struct tomoyo_policy_namespace *ns = | 1797 | struct tomoyo_policy_namespace *ns = |
| 1747 | container_of(head->r.ns, typeof(*ns), namespace_list); | 1798 | container_of(head->r.ns, typeof(*ns), namespace_list); |
| 1748 | struct list_head *list = &ns->group_list[idx]; | 1799 | struct list_head *list = &ns->group_list[idx]; |
| 1800 | |||
| 1749 | list_for_each_cookie(head->r.group, list) { | 1801 | list_for_each_cookie(head->r.group, list) { |
| 1750 | struct tomoyo_group *group = | 1802 | struct tomoyo_group *group = |
| 1751 | list_entry(head->r.group, typeof(*group), head.list); | 1803 | list_entry(head->r.group, typeof(*group), head.list); |
| 1804 | |||
| 1752 | list_for_each_cookie(head->r.acl, &group->member_list) { | 1805 | list_for_each_cookie(head->r.acl, &group->member_list) { |
| 1753 | struct tomoyo_acl_head *ptr = | 1806 | struct tomoyo_acl_head *ptr = |
| 1754 | list_entry(head->r.acl, typeof(*ptr), list); | 1807 | list_entry(head->r.acl, typeof(*ptr), list); |
| 1808 | |||
| 1755 | if (ptr->is_deleted) | 1809 | if (ptr->is_deleted) |
| 1756 | continue; | 1810 | continue; |
| 1757 | if (!tomoyo_flush(head)) | 1811 | if (!tomoyo_flush(head)) |
| @@ -1771,10 +1825,10 @@ static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx) | |||
| 1771 | head)->number); | 1825 | head)->number); |
| 1772 | } else if (idx == TOMOYO_ADDRESS_GROUP) { | 1826 | } else if (idx == TOMOYO_ADDRESS_GROUP) { |
| 1773 | char buffer[128]; | 1827 | char buffer[128]; |
| 1774 | |||
| 1775 | struct tomoyo_address_group *member = | 1828 | struct tomoyo_address_group *member = |
| 1776 | container_of(ptr, typeof(*member), | 1829 | container_of(ptr, typeof(*member), |
| 1777 | head); | 1830 | head); |
| 1831 | |||
| 1778 | tomoyo_print_ip(buffer, sizeof(buffer), | 1832 | tomoyo_print_ip(buffer, sizeof(buffer), |
| 1779 | &member->address); | 1833 | &member->address); |
| 1780 | tomoyo_io_printf(head, " %s", buffer); | 1834 | tomoyo_io_printf(head, " %s", buffer); |
| @@ -1802,6 +1856,7 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) | |||
| 1802 | struct tomoyo_policy_namespace *ns = | 1856 | struct tomoyo_policy_namespace *ns = |
| 1803 | container_of(head->r.ns, typeof(*ns), namespace_list); | 1857 | container_of(head->r.ns, typeof(*ns), namespace_list); |
| 1804 | struct list_head *list = &ns->policy_list[idx]; | 1858 | struct list_head *list = &ns->policy_list[idx]; |
| 1859 | |||
| 1805 | list_for_each_cookie(head->r.acl, list) { | 1860 | list_for_each_cookie(head->r.acl, list) { |
| 1806 | struct tomoyo_acl_head *acl = | 1861 | struct tomoyo_acl_head *acl = |
| 1807 | container_of(head->r.acl, typeof(*acl), list); | 1862 | container_of(head->r.acl, typeof(*acl), list); |
| @@ -1814,6 +1869,7 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) | |||
| 1814 | { | 1869 | { |
| 1815 | struct tomoyo_transition_control *ptr = | 1870 | struct tomoyo_transition_control *ptr = |
| 1816 | container_of(acl, typeof(*ptr), head); | 1871 | container_of(acl, typeof(*ptr), head); |
| 1872 | |||
| 1817 | tomoyo_print_namespace(head); | 1873 | tomoyo_print_namespace(head); |
| 1818 | tomoyo_set_string(head, tomoyo_transition_type | 1874 | tomoyo_set_string(head, tomoyo_transition_type |
| 1819 | [ptr->type]); | 1875 | [ptr->type]); |
| @@ -1829,6 +1885,7 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) | |||
| 1829 | { | 1885 | { |
| 1830 | struct tomoyo_aggregator *ptr = | 1886 | struct tomoyo_aggregator *ptr = |
| 1831 | container_of(acl, typeof(*ptr), head); | 1887 | container_of(acl, typeof(*ptr), head); |
| 1888 | |||
| 1832 | tomoyo_print_namespace(head); | 1889 | tomoyo_print_namespace(head); |
| 1833 | tomoyo_set_string(head, "aggregator "); | 1890 | tomoyo_set_string(head, "aggregator "); |
| 1834 | tomoyo_set_string(head, | 1891 | tomoyo_set_string(head, |
| @@ -1858,6 +1915,7 @@ static void tomoyo_read_exception(struct tomoyo_io_buffer *head) | |||
| 1858 | { | 1915 | { |
| 1859 | struct tomoyo_policy_namespace *ns = | 1916 | struct tomoyo_policy_namespace *ns = |
| 1860 | container_of(head->r.ns, typeof(*ns), namespace_list); | 1917 | container_of(head->r.ns, typeof(*ns), namespace_list); |
| 1918 | |||
| 1861 | if (head->r.eof) | 1919 | if (head->r.eof) |
| 1862 | return; | 1920 | return; |
| 1863 | while (head->r.step < TOMOYO_MAX_POLICY && | 1921 | while (head->r.step < TOMOYO_MAX_POLICY && |
| @@ -1921,6 +1979,7 @@ static atomic_t tomoyo_query_observers = ATOMIC_INIT(0); | |||
| 1921 | static int tomoyo_truncate(char *str) | 1979 | static int tomoyo_truncate(char *str) |
| 1922 | { | 1980 | { |
| 1923 | char *start = str; | 1981 | char *start = str; |
| 1982 | |||
| 1924 | while (*(unsigned char *) str > (unsigned char) ' ') | 1983 | while (*(unsigned char *) str > (unsigned char) ' ') |
| 1925 | str++; | 1984 | str++; |
| 1926 | *str = '\0'; | 1985 | *str = '\0'; |
| @@ -1943,6 +2002,7 @@ static void tomoyo_add_entry(struct tomoyo_domain_info *domain, char *header) | |||
| 1943 | char *symlink = NULL; | 2002 | char *symlink = NULL; |
| 1944 | char *cp = strchr(header, '\n'); | 2003 | char *cp = strchr(header, '\n'); |
| 1945 | int len; | 2004 | int len; |
| 2005 | |||
| 1946 | if (!cp) | 2006 | if (!cp) |
| 1947 | return; | 2007 | return; |
| 1948 | cp = strchr(cp + 1, '\n'); | 2008 | cp = strchr(cp + 1, '\n'); |
| @@ -2002,6 +2062,7 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) | |||
| 2002 | static unsigned int tomoyo_serial; | 2062 | static unsigned int tomoyo_serial; |
| 2003 | struct tomoyo_query entry = { }; | 2063 | struct tomoyo_query entry = { }; |
| 2004 | bool quota_exceeded = false; | 2064 | bool quota_exceeded = false; |
| 2065 | |||
| 2005 | va_start(args, fmt); | 2066 | va_start(args, fmt); |
| 2006 | len = vsnprintf((char *) &len, 1, fmt, args) + 1; | 2067 | len = vsnprintf((char *) &len, 1, fmt, args) + 1; |
| 2007 | va_end(args); | 2068 | va_end(args); |
| @@ -2063,8 +2124,7 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) | |||
| 2063 | (tomoyo_answer_wait, entry.answer || | 2124 | (tomoyo_answer_wait, entry.answer || |
| 2064 | !atomic_read(&tomoyo_query_observers), HZ)) | 2125 | !atomic_read(&tomoyo_query_observers), HZ)) |
| 2065 | break; | 2126 | break; |
| 2066 | else | 2127 | entry.timer++; |
| 2067 | entry.timer++; | ||
| 2068 | } | 2128 | } |
| 2069 | spin_lock(&tomoyo_query_list_lock); | 2129 | spin_lock(&tomoyo_query_list_lock); |
| 2070 | list_del(&entry.list); | 2130 | list_del(&entry.list); |
| @@ -2100,6 +2160,7 @@ static struct tomoyo_domain_info *tomoyo_find_domain_by_qid | |||
| 2100 | { | 2160 | { |
| 2101 | struct tomoyo_query *ptr; | 2161 | struct tomoyo_query *ptr; |
| 2102 | struct tomoyo_domain_info *domain = NULL; | 2162 | struct tomoyo_domain_info *domain = NULL; |
| 2163 | |||
| 2103 | spin_lock(&tomoyo_query_list_lock); | 2164 | spin_lock(&tomoyo_query_list_lock); |
| 2104 | list_for_each_entry(ptr, &tomoyo_query_list, list) { | 2165 | list_for_each_entry(ptr, &tomoyo_query_list, list) { |
| 2105 | if (ptr->serial != serial) | 2166 | if (ptr->serial != serial) |
| @@ -2142,15 +2203,15 @@ static void tomoyo_read_query(struct tomoyo_io_buffer *head) | |||
| 2142 | unsigned int pos = 0; | 2203 | unsigned int pos = 0; |
| 2143 | size_t len = 0; | 2204 | size_t len = 0; |
| 2144 | char *buf; | 2205 | char *buf; |
| 2206 | |||
| 2145 | if (head->r.w_pos) | 2207 | if (head->r.w_pos) |
| 2146 | return; | 2208 | return; |
| 2147 | if (head->read_buf) { | 2209 | kfree(head->read_buf); |
| 2148 | kfree(head->read_buf); | 2210 | head->read_buf = NULL; |
| 2149 | head->read_buf = NULL; | ||
| 2150 | } | ||
| 2151 | spin_lock(&tomoyo_query_list_lock); | 2211 | spin_lock(&tomoyo_query_list_lock); |
| 2152 | list_for_each(tmp, &tomoyo_query_list) { | 2212 | list_for_each(tmp, &tomoyo_query_list) { |
| 2153 | struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); | 2213 | struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); |
| 2214 | |||
| 2154 | if (pos++ != head->r.query_index) | 2215 | if (pos++ != head->r.query_index) |
| 2155 | continue; | 2216 | continue; |
| 2156 | len = ptr->query_len; | 2217 | len = ptr->query_len; |
| @@ -2168,6 +2229,7 @@ static void tomoyo_read_query(struct tomoyo_io_buffer *head) | |||
| 2168 | spin_lock(&tomoyo_query_list_lock); | 2229 | spin_lock(&tomoyo_query_list_lock); |
| 2169 | list_for_each(tmp, &tomoyo_query_list) { | 2230 | list_for_each(tmp, &tomoyo_query_list) { |
| 2170 | struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); | 2231 | struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); |
| 2232 | |||
| 2171 | if (pos++ != head->r.query_index) | 2233 | if (pos++ != head->r.query_index) |
| 2172 | continue; | 2234 | continue; |
| 2173 | /* | 2235 | /* |
| @@ -2202,9 +2264,11 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head) | |||
| 2202 | struct list_head *tmp; | 2264 | struct list_head *tmp; |
| 2203 | unsigned int serial; | 2265 | unsigned int serial; |
| 2204 | unsigned int answer; | 2266 | unsigned int answer; |
| 2267 | |||
| 2205 | spin_lock(&tomoyo_query_list_lock); | 2268 | spin_lock(&tomoyo_query_list_lock); |
| 2206 | list_for_each(tmp, &tomoyo_query_list) { | 2269 | list_for_each(tmp, &tomoyo_query_list) { |
| 2207 | struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); | 2270 | struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); |
| 2271 | |||
| 2208 | ptr->timer = 0; | 2272 | ptr->timer = 0; |
| 2209 | } | 2273 | } |
| 2210 | spin_unlock(&tomoyo_query_list_lock); | 2274 | spin_unlock(&tomoyo_query_list_lock); |
| @@ -2213,6 +2277,7 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head) | |||
| 2213 | spin_lock(&tomoyo_query_list_lock); | 2277 | spin_lock(&tomoyo_query_list_lock); |
| 2214 | list_for_each(tmp, &tomoyo_query_list) { | 2278 | list_for_each(tmp, &tomoyo_query_list) { |
| 2215 | struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); | 2279 | struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); |
| 2280 | |||
| 2216 | if (ptr->serial != serial) | 2281 | if (ptr->serial != serial) |
| 2217 | continue; | 2282 | continue; |
| 2218 | ptr->answer = answer; | 2283 | ptr->answer = answer; |
| @@ -2235,7 +2300,7 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head) | |||
| 2235 | static void tomoyo_read_version(struct tomoyo_io_buffer *head) | 2300 | static void tomoyo_read_version(struct tomoyo_io_buffer *head) |
| 2236 | { | 2301 | { |
| 2237 | if (!head->r.eof) { | 2302 | if (!head->r.eof) { |
| 2238 | tomoyo_io_printf(head, "2.5.0"); | 2303 | tomoyo_io_printf(head, "2.6.0"); |
| 2239 | head->r.eof = true; | 2304 | head->r.eof = true; |
| 2240 | } | 2305 | } |
| 2241 | } | 2306 | } |
| @@ -2287,6 +2352,7 @@ static void tomoyo_read_stat(struct tomoyo_io_buffer *head) | |||
| 2287 | { | 2352 | { |
| 2288 | u8 i; | 2353 | u8 i; |
| 2289 | unsigned int total = 0; | 2354 | unsigned int total = 0; |
| 2355 | |||
| 2290 | if (head->r.eof) | 2356 | if (head->r.eof) |
| 2291 | return; | 2357 | return; |
| 2292 | for (i = 0; i < TOMOYO_MAX_POLICY_STAT; i++) { | 2358 | for (i = 0; i < TOMOYO_MAX_POLICY_STAT; i++) { |
| @@ -2295,9 +2361,9 @@ static void tomoyo_read_stat(struct tomoyo_io_buffer *head) | |||
| 2295 | tomoyo_stat_updated[i]); | 2361 | tomoyo_stat_updated[i]); |
| 2296 | if (tomoyo_stat_modified[i]) { | 2362 | if (tomoyo_stat_modified[i]) { |
| 2297 | struct tomoyo_time stamp; | 2363 | struct tomoyo_time stamp; |
| 2364 | |||
| 2298 | tomoyo_convert_time(tomoyo_stat_modified[i], &stamp); | 2365 | tomoyo_convert_time(tomoyo_stat_modified[i], &stamp); |
| 2299 | tomoyo_io_printf(head, " (Last: %04u/%02u/%02u " | 2366 | tomoyo_io_printf(head, " (Last: %04u/%02u/%02u %02u:%02u:%02u)", |
| 2300 | "%02u:%02u:%02u)", | ||
| 2301 | stamp.year, stamp.month, stamp.day, | 2367 | stamp.year, stamp.month, stamp.day, |
| 2302 | stamp.hour, stamp.min, stamp.sec); | 2368 | stamp.hour, stamp.min, stamp.sec); |
| 2303 | } | 2369 | } |
| @@ -2305,6 +2371,7 @@ static void tomoyo_read_stat(struct tomoyo_io_buffer *head) | |||
| 2305 | } | 2371 | } |
| 2306 | for (i = 0; i < TOMOYO_MAX_MEMORY_STAT; i++) { | 2372 | for (i = 0; i < TOMOYO_MAX_MEMORY_STAT; i++) { |
| 2307 | unsigned int used = tomoyo_memory_used[i]; | 2373 | unsigned int used = tomoyo_memory_used[i]; |
| 2374 | |||
| 2308 | total += used; | 2375 | total += used; |
| 2309 | tomoyo_io_printf(head, "Memory used by %-22s %10u", | 2376 | tomoyo_io_printf(head, "Memory used by %-22s %10u", |
| 2310 | tomoyo_memory_headers[i], used); | 2377 | tomoyo_memory_headers[i], used); |
| @@ -2329,6 +2396,7 @@ static int tomoyo_write_stat(struct tomoyo_io_buffer *head) | |||
| 2329 | { | 2396 | { |
| 2330 | char *data = head->write_buf; | 2397 | char *data = head->write_buf; |
| 2331 | u8 i; | 2398 | u8 i; |
| 2399 | |||
| 2332 | if (tomoyo_str_starts(&data, "Memory used by ")) | 2400 | if (tomoyo_str_starts(&data, "Memory used by ")) |
| 2333 | for (i = 0; i < TOMOYO_MAX_MEMORY_STAT; i++) | 2401 | for (i = 0; i < TOMOYO_MAX_MEMORY_STAT; i++) |
| 2334 | if (tomoyo_str_starts(&data, tomoyo_memory_headers[i])) | 2402 | if (tomoyo_str_starts(&data, tomoyo_memory_headers[i])) |
| @@ -2457,6 +2525,7 @@ int tomoyo_open_control(const u8 type, struct file *file) | |||
| 2457 | __poll_t tomoyo_poll_control(struct file *file, poll_table *wait) | 2525 | __poll_t tomoyo_poll_control(struct file *file, poll_table *wait) |
| 2458 | { | 2526 | { |
| 2459 | struct tomoyo_io_buffer *head = file->private_data; | 2527 | struct tomoyo_io_buffer *head = file->private_data; |
| 2528 | |||
| 2460 | if (head->poll) | 2529 | if (head->poll) |
| 2461 | return head->poll(file, wait) | EPOLLOUT | EPOLLWRNORM; | 2530 | return head->poll(file, wait) | EPOLLOUT | EPOLLWRNORM; |
| 2462 | return EPOLLIN | EPOLLRDNORM | EPOLLOUT | EPOLLWRNORM; | 2531 | return EPOLLIN | EPOLLRDNORM | EPOLLOUT | EPOLLWRNORM; |
| @@ -2472,6 +2541,7 @@ __poll_t tomoyo_poll_control(struct file *file, poll_table *wait) | |||
| 2472 | static inline void tomoyo_set_namespace_cursor(struct tomoyo_io_buffer *head) | 2541 | static inline void tomoyo_set_namespace_cursor(struct tomoyo_io_buffer *head) |
| 2473 | { | 2542 | { |
| 2474 | struct list_head *ns; | 2543 | struct list_head *ns; |
| 2544 | |||
| 2475 | if (head->type != TOMOYO_EXCEPTIONPOLICY && | 2545 | if (head->type != TOMOYO_EXCEPTIONPOLICY && |
| 2476 | head->type != TOMOYO_PROFILE) | 2546 | head->type != TOMOYO_PROFILE) |
| 2477 | return; | 2547 | return; |
| @@ -2517,7 +2587,7 @@ ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, | |||
| 2517 | int idx; | 2587 | int idx; |
| 2518 | 2588 | ||
| 2519 | if (!head->read) | 2589 | if (!head->read) |
| 2520 | return -ENOSYS; | 2590 | return -EINVAL; |
| 2521 | if (mutex_lock_interruptible(&head->io_sem)) | 2591 | if (mutex_lock_interruptible(&head->io_sem)) |
| 2522 | return -EINTR; | 2592 | return -EINTR; |
| 2523 | head->read_user_buf = buffer; | 2593 | head->read_user_buf = buffer; |
| @@ -2557,6 +2627,7 @@ static int tomoyo_parse_policy(struct tomoyo_io_buffer *head, char *line) | |||
| 2557 | head->type == TOMOYO_PROFILE) { | 2627 | head->type == TOMOYO_PROFILE) { |
| 2558 | if (*line == '<') { | 2628 | if (*line == '<') { |
| 2559 | char *cp = strchr(line, ' '); | 2629 | char *cp = strchr(line, ' '); |
| 2630 | |||
| 2560 | if (cp) { | 2631 | if (cp) { |
| 2561 | *cp++ = '\0'; | 2632 | *cp++ = '\0'; |
| 2562 | head->w.ns = tomoyo_assign_namespace(line); | 2633 | head->w.ns = tomoyo_assign_namespace(line); |
| @@ -2589,8 +2660,9 @@ ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head, | |||
| 2589 | size_t avail_len = buffer_len; | 2660 | size_t avail_len = buffer_len; |
| 2590 | char *cp0 = head->write_buf; | 2661 | char *cp0 = head->write_buf; |
| 2591 | int idx; | 2662 | int idx; |
| 2663 | |||
| 2592 | if (!head->write) | 2664 | if (!head->write) |
| 2593 | return -ENOSYS; | 2665 | return -EINVAL; |
| 2594 | if (!access_ok(buffer, buffer_len)) | 2666 | if (!access_ok(buffer, buffer_len)) |
| 2595 | return -EFAULT; | 2667 | return -EFAULT; |
| 2596 | if (mutex_lock_interruptible(&head->io_sem)) | 2668 | if (mutex_lock_interruptible(&head->io_sem)) |
| @@ -2600,9 +2672,11 @@ ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head, | |||
| 2600 | /* Read a line and dispatch it to the policy handler. */ | 2672 | /* Read a line and dispatch it to the policy handler. */ |
| 2601 | while (avail_len > 0) { | 2673 | while (avail_len > 0) { |
| 2602 | char c; | 2674 | char c; |
| 2675 | |||
| 2603 | if (head->w.avail >= head->writebuf_size - 1) { | 2676 | if (head->w.avail >= head->writebuf_size - 1) { |
| 2604 | const int len = head->writebuf_size * 2; | 2677 | const int len = head->writebuf_size * 2; |
| 2605 | char *cp = kzalloc(len, GFP_NOFS); | 2678 | char *cp = kzalloc(len, GFP_NOFS); |
| 2679 | |||
| 2606 | if (!cp) { | 2680 | if (!cp) { |
| 2607 | error = -ENOMEM; | 2681 | error = -ENOMEM; |
| 2608 | break; | 2682 | break; |
| @@ -2701,30 +2775,32 @@ void tomoyo_check_profile(void) | |||
| 2701 | { | 2775 | { |
| 2702 | struct tomoyo_domain_info *domain; | 2776 | struct tomoyo_domain_info *domain; |
| 2703 | const int idx = tomoyo_read_lock(); | 2777 | const int idx = tomoyo_read_lock(); |
| 2778 | |||
| 2704 | tomoyo_policy_loaded = true; | 2779 | tomoyo_policy_loaded = true; |
| 2705 | printk(KERN_INFO "TOMOYO: 2.5.0\n"); | 2780 | pr_info("TOMOYO: 2.6.0\n"); |
| 2706 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { | 2781 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { |
| 2707 | const u8 profile = domain->profile; | 2782 | const u8 profile = domain->profile; |
| 2708 | const struct tomoyo_policy_namespace *ns = domain->ns; | 2783 | struct tomoyo_policy_namespace *ns = domain->ns; |
| 2709 | if (ns->profile_version != 20110903) | 2784 | |
| 2710 | printk(KERN_ERR | 2785 | if (ns->profile_version == 20110903) { |
| 2711 | "Profile version %u is not supported.\n", | 2786 | pr_info_once("Converting profile version from %u to %u.\n", |
| 2787 | 20110903, 20150505); | ||
| 2788 | ns->profile_version = 20150505; | ||
| 2789 | } | ||
| 2790 | if (ns->profile_version != 20150505) | ||
| 2791 | pr_err("Profile version %u is not supported.\n", | ||
| 2712 | ns->profile_version); | 2792 | ns->profile_version); |
| 2713 | else if (!ns->profile_ptr[profile]) | 2793 | else if (!ns->profile_ptr[profile]) |
| 2714 | printk(KERN_ERR | 2794 | pr_err("Profile %u (used by '%s') is not defined.\n", |
| 2715 | "Profile %u (used by '%s') is not defined.\n", | ||
| 2716 | profile, domain->domainname->name); | 2795 | profile, domain->domainname->name); |
| 2717 | else | 2796 | else |
| 2718 | continue; | 2797 | continue; |
| 2719 | printk(KERN_ERR | 2798 | pr_err("Userland tools for TOMOYO 2.6 must be installed and policy must be initialized.\n"); |
| 2720 | "Userland tools for TOMOYO 2.5 must be installed and " | 2799 | pr_err("Please see https://tomoyo.osdn.jp/2.6/ for more information.\n"); |
| 2721 | "policy must be initialized.\n"); | ||
| 2722 | printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/2.5/ " | ||
| 2723 | "for more information.\n"); | ||
| 2724 | panic("STOP!"); | 2800 | panic("STOP!"); |
| 2725 | } | 2801 | } |
| 2726 | tomoyo_read_unlock(idx); | 2802 | tomoyo_read_unlock(idx); |
| 2727 | printk(KERN_INFO "Mandatory Access Control activated.\n"); | 2803 | pr_info("Mandatory Access Control activated.\n"); |
| 2728 | } | 2804 | } |
| 2729 | 2805 | ||
| 2730 | /** | 2806 | /** |
| @@ -2743,9 +2819,11 @@ void __init tomoyo_load_builtin_policy(void) | |||
| 2743 | #include "builtin-policy.h" | 2819 | #include "builtin-policy.h" |
| 2744 | u8 i; | 2820 | u8 i; |
| 2745 | const int idx = tomoyo_read_lock(); | 2821 | const int idx = tomoyo_read_lock(); |
| 2822 | |||
| 2746 | for (i = 0; i < 5; i++) { | 2823 | for (i = 0; i < 5; i++) { |
| 2747 | struct tomoyo_io_buffer head = { }; | 2824 | struct tomoyo_io_buffer head = { }; |
| 2748 | char *start = ""; | 2825 | char *start = ""; |
| 2826 | |||
| 2749 | switch (i) { | 2827 | switch (i) { |
| 2750 | case 0: | 2828 | case 0: |
| 2751 | start = tomoyo_builtin_profile; | 2829 | start = tomoyo_builtin_profile; |
| @@ -2775,6 +2853,7 @@ void __init tomoyo_load_builtin_policy(void) | |||
| 2775 | } | 2853 | } |
| 2776 | while (1) { | 2854 | while (1) { |
| 2777 | char *end = strchr(start, '\n'); | 2855 | char *end = strchr(start, '\n'); |
| 2856 | |||
| 2778 | if (!end) | 2857 | if (!end) |
| 2779 | break; | 2858 | break; |
| 2780 | *end = '\0'; | 2859 | *end = '\0'; |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 539bcdd30bb8..050473df5809 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
| @@ -10,6 +10,8 @@ | |||
| 10 | #ifndef _SECURITY_TOMOYO_COMMON_H | 10 | #ifndef _SECURITY_TOMOYO_COMMON_H |
| 11 | #define _SECURITY_TOMOYO_COMMON_H | 11 | #define _SECURITY_TOMOYO_COMMON_H |
| 12 | 12 | ||
| 13 | #define pr_fmt(fmt) fmt | ||
| 14 | |||
| 13 | #include <linux/ctype.h> | 15 | #include <linux/ctype.h> |
| 14 | #include <linux/string.h> | 16 | #include <linux/string.h> |
| 15 | #include <linux/mm.h> | 17 | #include <linux/mm.h> |
| @@ -29,6 +31,7 @@ | |||
| 29 | #include <linux/in.h> | 31 | #include <linux/in.h> |
| 30 | #include <linux/in6.h> | 32 | #include <linux/in6.h> |
| 31 | #include <linux/un.h> | 33 | #include <linux/un.h> |
| 34 | #include <linux/lsm_hooks.h> | ||
| 32 | #include <net/sock.h> | 35 | #include <net/sock.h> |
| 33 | #include <net/af_unix.h> | 36 | #include <net/af_unix.h> |
| 34 | #include <net/ip.h> | 37 | #include <net/ip.h> |
| @@ -681,11 +684,12 @@ struct tomoyo_domain_info { | |||
| 681 | const struct tomoyo_path_info *domainname; | 684 | const struct tomoyo_path_info *domainname; |
| 682 | /* Namespace for this domain. Never NULL. */ | 685 | /* Namespace for this domain. Never NULL. */ |
| 683 | struct tomoyo_policy_namespace *ns; | 686 | struct tomoyo_policy_namespace *ns; |
| 687 | /* Group numbers to use. */ | ||
| 688 | unsigned long group[TOMOYO_MAX_ACL_GROUPS / BITS_PER_LONG]; | ||
| 684 | u8 profile; /* Profile number to use. */ | 689 | u8 profile; /* Profile number to use. */ |
| 685 | u8 group; /* Group number to use. */ | ||
| 686 | bool is_deleted; /* Delete flag. */ | 690 | bool is_deleted; /* Delete flag. */ |
| 687 | bool flags[TOMOYO_MAX_DOMAIN_INFO_FLAGS]; | 691 | bool flags[TOMOYO_MAX_DOMAIN_INFO_FLAGS]; |
| 688 | atomic_t users; /* Number of referring credentials. */ | 692 | atomic_t users; /* Number of referring tasks. */ |
| 689 | }; | 693 | }; |
| 690 | 694 | ||
| 691 | /* | 695 | /* |
| @@ -787,9 +791,9 @@ struct tomoyo_acl_param { | |||
| 787 | * interfaces. | 791 | * interfaces. |
| 788 | */ | 792 | */ |
| 789 | struct tomoyo_io_buffer { | 793 | struct tomoyo_io_buffer { |
| 790 | void (*read) (struct tomoyo_io_buffer *); | 794 | void (*read)(struct tomoyo_io_buffer *head); |
| 791 | int (*write) (struct tomoyo_io_buffer *); | 795 | int (*write)(struct tomoyo_io_buffer *head); |
| 792 | __poll_t (*poll) (struct file *file, poll_table *wait); | 796 | __poll_t (*poll)(struct file *file, poll_table *wait); |
| 793 | /* Exclusive lock for this structure. */ | 797 | /* Exclusive lock for this structure. */ |
| 794 | struct mutex io_sem; | 798 | struct mutex io_sem; |
| 795 | char __user *read_user_buf; | 799 | char __user *read_user_buf; |
| @@ -906,12 +910,18 @@ struct tomoyo_policy_namespace { | |||
| 906 | struct list_head acl_group[TOMOYO_MAX_ACL_GROUPS]; | 910 | struct list_head acl_group[TOMOYO_MAX_ACL_GROUPS]; |
| 907 | /* List for connecting to tomoyo_namespace_list list. */ | 911 | /* List for connecting to tomoyo_namespace_list list. */ |
| 908 | struct list_head namespace_list; | 912 | struct list_head namespace_list; |
| 909 | /* Profile version. Currently only 20110903 is defined. */ | 913 | /* Profile version. Currently only 20150505 is defined. */ |
| 910 | unsigned int profile_version; | 914 | unsigned int profile_version; |
| 911 | /* Name of this namespace (e.g. "<kernel>", "</usr/sbin/httpd>" ). */ | 915 | /* Name of this namespace (e.g. "<kernel>", "</usr/sbin/httpd>" ). */ |
| 912 | const char *name; | 916 | const char *name; |
| 913 | }; | 917 | }; |
| 914 | 918 | ||
| 919 | /* Structure for "struct task_struct"->security. */ | ||
| 920 | struct tomoyo_task { | ||
| 921 | struct tomoyo_domain_info *domain_info; | ||
| 922 | struct tomoyo_domain_info *old_domain_info; | ||
| 923 | }; | ||
| 924 | |||
| 915 | /********** Function prototypes. **********/ | 925 | /********** Function prototypes. **********/ |
| 916 | 926 | ||
| 917 | bool tomoyo_address_matches_group(const bool is_ipv6, const __be32 *address, | 927 | bool tomoyo_address_matches_group(const bool is_ipv6, const __be32 *address, |
| @@ -1020,6 +1030,7 @@ ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head, | |||
| 1020 | struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param); | 1030 | struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param); |
| 1021 | struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, | 1031 | struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, |
| 1022 | const bool transit); | 1032 | const bool transit); |
| 1033 | struct tomoyo_domain_info *tomoyo_domain(void); | ||
| 1023 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); | 1034 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); |
| 1024 | struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param, | 1035 | struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param, |
| 1025 | const u8 idx); | 1036 | const u8 idx); |
| @@ -1034,8 +1045,8 @@ void *tomoyo_commit_ok(void *data, const unsigned int size); | |||
| 1034 | void __init tomoyo_load_builtin_policy(void); | 1045 | void __init tomoyo_load_builtin_policy(void); |
| 1035 | void __init tomoyo_mm_init(void); | 1046 | void __init tomoyo_mm_init(void); |
| 1036 | void tomoyo_check_acl(struct tomoyo_request_info *r, | 1047 | void tomoyo_check_acl(struct tomoyo_request_info *r, |
| 1037 | bool (*check_entry) (struct tomoyo_request_info *, | 1048 | bool (*check_entry)(struct tomoyo_request_info *, |
| 1038 | const struct tomoyo_acl_info *)); | 1049 | const struct tomoyo_acl_info *)); |
| 1039 | void tomoyo_check_profile(void); | 1050 | void tomoyo_check_profile(void); |
| 1040 | void tomoyo_convert_time(time64_t time, struct tomoyo_time *stamp); | 1051 | void tomoyo_convert_time(time64_t time, struct tomoyo_time *stamp); |
| 1041 | void tomoyo_del_condition(struct list_head *element); | 1052 | void tomoyo_del_condition(struct list_head *element); |
| @@ -1062,6 +1073,7 @@ void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt, | |||
| 1062 | /********** External variable definitions. **********/ | 1073 | /********** External variable definitions. **********/ |
| 1063 | 1074 | ||
| 1064 | extern bool tomoyo_policy_loaded; | 1075 | extern bool tomoyo_policy_loaded; |
| 1076 | extern int tomoyo_enabled; | ||
| 1065 | extern const char * const tomoyo_condition_keyword | 1077 | extern const char * const tomoyo_condition_keyword |
| 1066 | [TOMOYO_MAX_CONDITION_KEYWORD]; | 1078 | [TOMOYO_MAX_CONDITION_KEYWORD]; |
| 1067 | extern const char * const tomoyo_dif[TOMOYO_MAX_DOMAIN_INFO_FLAGS]; | 1079 | extern const char * const tomoyo_dif[TOMOYO_MAX_DOMAIN_INFO_FLAGS]; |
| @@ -1085,6 +1097,7 @@ extern struct tomoyo_domain_info tomoyo_kernel_domain; | |||
| 1085 | extern struct tomoyo_policy_namespace tomoyo_kernel_namespace; | 1097 | extern struct tomoyo_policy_namespace tomoyo_kernel_namespace; |
| 1086 | extern unsigned int tomoyo_memory_quota[TOMOYO_MAX_MEMORY_STAT]; | 1098 | extern unsigned int tomoyo_memory_quota[TOMOYO_MAX_MEMORY_STAT]; |
| 1087 | extern unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT]; | 1099 | extern unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT]; |
| 1100 | extern struct lsm_blob_sizes tomoyo_blob_sizes; | ||
| 1088 | 1101 | ||
| 1089 | /********** Inlined functions. **********/ | 1102 | /********** Inlined functions. **********/ |
| 1090 | 1103 | ||
| @@ -1121,6 +1134,7 @@ static inline void tomoyo_read_unlock(int idx) | |||
| 1121 | static inline pid_t tomoyo_sys_getppid(void) | 1134 | static inline pid_t tomoyo_sys_getppid(void) |
| 1122 | { | 1135 | { |
| 1123 | pid_t pid; | 1136 | pid_t pid; |
| 1137 | |||
| 1124 | rcu_read_lock(); | 1138 | rcu_read_lock(); |
| 1125 | pid = task_tgid_vnr(rcu_dereference(current->real_parent)); | 1139 | pid = task_tgid_vnr(rcu_dereference(current->real_parent)); |
| 1126 | rcu_read_unlock(); | 1140 | rcu_read_unlock(); |
| @@ -1197,26 +1211,15 @@ static inline void tomoyo_put_group(struct tomoyo_group *group) | |||
| 1197 | } | 1211 | } |
| 1198 | 1212 | ||
| 1199 | /** | 1213 | /** |
| 1200 | * tomoyo_domain - Get "struct tomoyo_domain_info" for current thread. | 1214 | * tomoyo_task - Get "struct tomoyo_task" for specified thread. |
| 1201 | * | ||
| 1202 | * Returns pointer to "struct tomoyo_domain_info" for current thread. | ||
| 1203 | */ | ||
| 1204 | static inline struct tomoyo_domain_info *tomoyo_domain(void) | ||
| 1205 | { | ||
| 1206 | return current_cred()->security; | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | /** | ||
| 1210 | * tomoyo_real_domain - Get "struct tomoyo_domain_info" for specified thread. | ||
| 1211 | * | 1215 | * |
| 1212 | * @task: Pointer to "struct task_struct". | 1216 | * @task - Pointer to "struct task_struct". |
| 1213 | * | 1217 | * |
| 1214 | * Returns pointer to "struct tomoyo_security" for specified thread. | 1218 | * Returns pointer to "struct tomoyo_task" for specified thread. |
| 1215 | */ | 1219 | */ |
| 1216 | static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct | 1220 | static inline struct tomoyo_task *tomoyo_task(struct task_struct *task) |
| 1217 | *task) | ||
| 1218 | { | 1221 | { |
| 1219 | return task_cred_xxx(task, security); | 1222 | return task->security + tomoyo_blob_sizes.lbs_task; |
| 1220 | } | 1223 | } |
| 1221 | 1224 | ||
| 1222 | /** | 1225 | /** |
diff --git a/security/tomoyo/condition.c b/security/tomoyo/condition.c index 8d0e1b9c9c57..8f6d57c15df6 100644 --- a/security/tomoyo/condition.c +++ b/security/tomoyo/condition.c | |||
| @@ -28,9 +28,11 @@ static bool tomoyo_argv(const unsigned int index, const char *arg_ptr, | |||
| 28 | { | 28 | { |
| 29 | int i; | 29 | int i; |
| 30 | struct tomoyo_path_info arg; | 30 | struct tomoyo_path_info arg; |
| 31 | |||
| 31 | arg.name = arg_ptr; | 32 | arg.name = arg_ptr; |
| 32 | for (i = 0; i < argc; argv++, checked++, i++) { | 33 | for (i = 0; i < argc; argv++, checked++, i++) { |
| 33 | bool result; | 34 | bool result; |
| 35 | |||
| 34 | if (index != argv->index) | 36 | if (index != argv->index) |
| 35 | continue; | 37 | continue; |
| 36 | *checked = 1; | 38 | *checked = 1; |
| @@ -62,12 +64,14 @@ static bool tomoyo_envp(const char *env_name, const char *env_value, | |||
| 62 | int i; | 64 | int i; |
| 63 | struct tomoyo_path_info name; | 65 | struct tomoyo_path_info name; |
| 64 | struct tomoyo_path_info value; | 66 | struct tomoyo_path_info value; |
| 67 | |||
| 65 | name.name = env_name; | 68 | name.name = env_name; |
| 66 | tomoyo_fill_path_info(&name); | 69 | tomoyo_fill_path_info(&name); |
| 67 | value.name = env_value; | 70 | value.name = env_value; |
| 68 | tomoyo_fill_path_info(&value); | 71 | tomoyo_fill_path_info(&value); |
| 69 | for (i = 0; i < envc; envp++, checked++, i++) { | 72 | for (i = 0; i < envc; envp++, checked++, i++) { |
| 70 | bool result; | 73 | bool result; |
| 74 | |||
| 71 | if (!tomoyo_path_matches_pattern(&name, envp->name)) | 75 | if (!tomoyo_path_matches_pattern(&name, envp->name)) |
| 72 | continue; | 76 | continue; |
| 73 | *checked = 1; | 77 | *checked = 1; |
| @@ -113,6 +117,7 @@ static bool tomoyo_scan_bprm(struct tomoyo_execve *ee, | |||
| 113 | bool result = true; | 117 | bool result = true; |
| 114 | u8 local_checked[32]; | 118 | u8 local_checked[32]; |
| 115 | u8 *checked; | 119 | u8 *checked; |
| 120 | |||
| 116 | if (argc + envc <= sizeof(local_checked)) { | 121 | if (argc + envc <= sizeof(local_checked)) { |
| 117 | checked = local_checked; | 122 | checked = local_checked; |
| 118 | memset(local_checked, 0, sizeof(local_checked)); | 123 | memset(local_checked, 0, sizeof(local_checked)); |
| @@ -131,6 +136,7 @@ static bool tomoyo_scan_bprm(struct tomoyo_execve *ee, | |||
| 131 | /* Read. */ | 136 | /* Read. */ |
| 132 | const char *kaddr = dump->data; | 137 | const char *kaddr = dump->data; |
| 133 | const unsigned char c = kaddr[offset++]; | 138 | const unsigned char c = kaddr[offset++]; |
| 139 | |||
| 134 | if (c && arg_len < TOMOYO_EXEC_TMPSIZE - 10) { | 140 | if (c && arg_len < TOMOYO_EXEC_TMPSIZE - 10) { |
| 135 | if (c == '\\') { | 141 | if (c == '\\') { |
| 136 | arg_ptr[arg_len++] = '\\'; | 142 | arg_ptr[arg_len++] = '\\'; |
| @@ -160,6 +166,7 @@ static bool tomoyo_scan_bprm(struct tomoyo_execve *ee, | |||
| 160 | argv_count--; | 166 | argv_count--; |
| 161 | } else if (envp_count) { | 167 | } else if (envp_count) { |
| 162 | char *cp = strchr(arg_ptr, '='); | 168 | char *cp = strchr(arg_ptr, '='); |
| 169 | |||
| 163 | if (cp) { | 170 | if (cp) { |
| 164 | *cp = '\0'; | 171 | *cp = '\0'; |
| 165 | if (!tomoyo_envp(arg_ptr, cp + 1, | 172 | if (!tomoyo_envp(arg_ptr, cp + 1, |
| @@ -182,6 +189,7 @@ static bool tomoyo_scan_bprm(struct tomoyo_execve *ee, | |||
| 182 | out: | 189 | out: |
| 183 | if (result) { | 190 | if (result) { |
| 184 | int i; | 191 | int i; |
| 192 | |||
| 185 | /* Check not-yet-checked entries. */ | 193 | /* Check not-yet-checked entries. */ |
| 186 | for (i = 0; i < argc; i++) { | 194 | for (i = 0; i < argc; i++) { |
| 187 | if (checked[i]) | 195 | if (checked[i]) |
| @@ -229,6 +237,7 @@ static bool tomoyo_scan_exec_realpath(struct file *file, | |||
| 229 | { | 237 | { |
| 230 | bool result; | 238 | bool result; |
| 231 | struct tomoyo_path_info exe; | 239 | struct tomoyo_path_info exe; |
| 240 | |||
| 232 | if (!file) | 241 | if (!file) |
| 233 | return false; | 242 | return false; |
| 234 | exe.name = tomoyo_realpath_from_path(&file->f_path); | 243 | exe.name = tomoyo_realpath_from_path(&file->f_path); |
| @@ -250,6 +259,7 @@ static bool tomoyo_scan_exec_realpath(struct file *file, | |||
| 250 | static const struct tomoyo_path_info *tomoyo_get_dqword(char *start) | 259 | static const struct tomoyo_path_info *tomoyo_get_dqword(char *start) |
| 251 | { | 260 | { |
| 252 | char *cp = start + strlen(start) - 1; | 261 | char *cp = start + strlen(start) - 1; |
| 262 | |||
| 253 | if (cp == start || *start++ != '"' || *cp != '"') | 263 | if (cp == start || *start++ != '"' || *cp != '"') |
| 254 | return NULL; | 264 | return NULL; |
| 255 | *cp = '\0'; | 265 | *cp = '\0'; |
| @@ -270,6 +280,7 @@ static bool tomoyo_parse_name_union_quoted(struct tomoyo_acl_param *param, | |||
| 270 | struct tomoyo_name_union *ptr) | 280 | struct tomoyo_name_union *ptr) |
| 271 | { | 281 | { |
| 272 | char *filename = param->data; | 282 | char *filename = param->data; |
| 283 | |||
| 273 | if (*filename == '@') | 284 | if (*filename == '@') |
| 274 | return tomoyo_parse_name_union(param, ptr); | 285 | return tomoyo_parse_name_union(param, ptr); |
| 275 | ptr->filename = tomoyo_get_dqword(filename); | 286 | ptr->filename = tomoyo_get_dqword(filename); |
| @@ -310,6 +321,7 @@ static bool tomoyo_parse_envp(char *left, char *right, | |||
| 310 | const struct tomoyo_path_info *name; | 321 | const struct tomoyo_path_info *name; |
| 311 | const struct tomoyo_path_info *value; | 322 | const struct tomoyo_path_info *value; |
| 312 | char *cp = left + strlen(left) - 1; | 323 | char *cp = left + strlen(left) - 1; |
| 324 | |||
| 313 | if (*cp-- != ']' || *cp != '"') | 325 | if (*cp-- != ']' || *cp != '"') |
| 314 | goto out; | 326 | goto out; |
| 315 | *cp = '\0'; | 327 | *cp = '\0'; |
| @@ -364,6 +376,7 @@ static inline bool tomoyo_same_condition(const struct tomoyo_condition *a, | |||
| 364 | static u8 tomoyo_condition_type(const char *word) | 376 | static u8 tomoyo_condition_type(const char *word) |
| 365 | { | 377 | { |
| 366 | u8 i; | 378 | u8 i; |
| 379 | |||
| 367 | for (i = 0; i < TOMOYO_MAX_CONDITION_KEYWORD; i++) { | 380 | for (i = 0; i < TOMOYO_MAX_CONDITION_KEYWORD; i++) { |
| 368 | if (!strcmp(word, tomoyo_condition_keyword[i])) | 381 | if (!strcmp(word, tomoyo_condition_keyword[i])) |
| 369 | break; | 382 | break; |
| @@ -395,6 +408,7 @@ static struct tomoyo_condition *tomoyo_commit_condition | |||
| 395 | { | 408 | { |
| 396 | struct tomoyo_condition *ptr; | 409 | struct tomoyo_condition *ptr; |
| 397 | bool found = false; | 410 | bool found = false; |
| 411 | |||
| 398 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) { | 412 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) { |
| 399 | dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__); | 413 | dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__); |
| 400 | ptr = NULL; | 414 | ptr = NULL; |
| @@ -442,12 +456,14 @@ static char *tomoyo_get_transit_preference(struct tomoyo_acl_param *param, | |||
| 442 | { | 456 | { |
| 443 | char * const pos = param->data; | 457 | char * const pos = param->data; |
| 444 | bool flag; | 458 | bool flag; |
| 459 | |||
| 445 | if (*pos == '<') { | 460 | if (*pos == '<') { |
| 446 | e->transit = tomoyo_get_domainname(param); | 461 | e->transit = tomoyo_get_domainname(param); |
| 447 | goto done; | 462 | goto done; |
| 448 | } | 463 | } |
| 449 | { | 464 | { |
| 450 | char *cp = strchr(pos, ' '); | 465 | char *cp = strchr(pos, ' '); |
| 466 | |||
| 451 | if (cp) | 467 | if (cp) |
| 452 | *cp = '\0'; | 468 | *cp = '\0'; |
| 453 | flag = tomoyo_correct_path(pos) || !strcmp(pos, "keep") || | 469 | flag = tomoyo_correct_path(pos) || !strcmp(pos, "keep") || |
| @@ -489,6 +505,7 @@ struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param) | |||
| 489 | tomoyo_get_transit_preference(param, &e); | 505 | tomoyo_get_transit_preference(param, &e); |
| 490 | char * const end_of_string = start_of_string + strlen(start_of_string); | 506 | char * const end_of_string = start_of_string + strlen(start_of_string); |
| 491 | char *pos; | 507 | char *pos; |
| 508 | |||
| 492 | rerun: | 509 | rerun: |
| 493 | pos = start_of_string; | 510 | pos = start_of_string; |
| 494 | while (1) { | 511 | while (1) { |
| @@ -498,6 +515,7 @@ rerun: | |||
| 498 | char *cp; | 515 | char *cp; |
| 499 | char *right_word; | 516 | char *right_word; |
| 500 | bool is_not; | 517 | bool is_not; |
| 518 | |||
| 501 | if (!*left_word) | 519 | if (!*left_word) |
| 502 | break; | 520 | break; |
| 503 | /* | 521 | /* |
| @@ -622,8 +640,8 @@ rerun: | |||
| 622 | } | 640 | } |
| 623 | store_value: | 641 | store_value: |
| 624 | if (!condp) { | 642 | if (!condp) { |
| 625 | dprintk(KERN_WARNING "%u: dry_run left=%u right=%u " | 643 | dprintk(KERN_WARNING "%u: dry_run left=%u right=%u match=%u\n", |
| 626 | "match=%u\n", __LINE__, left, right, !is_not); | 644 | __LINE__, left, right, !is_not); |
| 627 | continue; | 645 | continue; |
| 628 | } | 646 | } |
| 629 | condp->left = left; | 647 | condp->left = left; |
| @@ -660,6 +678,7 @@ store_value: | |||
| 660 | envp = (struct tomoyo_envp *) (argv + e.argc); | 678 | envp = (struct tomoyo_envp *) (argv + e.argc); |
| 661 | { | 679 | { |
| 662 | bool flag = false; | 680 | bool flag = false; |
| 681 | |||
| 663 | for (pos = start_of_string; pos < end_of_string; pos++) { | 682 | for (pos = start_of_string; pos < end_of_string; pos++) { |
| 664 | if (*pos) | 683 | if (*pos) |
| 665 | continue; | 684 | continue; |
| @@ -698,6 +717,7 @@ void tomoyo_get_attributes(struct tomoyo_obj_info *obj) | |||
| 698 | 717 | ||
| 699 | for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) { | 718 | for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) { |
| 700 | struct inode *inode; | 719 | struct inode *inode; |
| 720 | |||
| 701 | switch (i) { | 721 | switch (i) { |
| 702 | case TOMOYO_PATH1: | 722 | case TOMOYO_PATH1: |
| 703 | dentry = obj->path1.dentry; | 723 | dentry = obj->path1.dentry; |
| @@ -718,6 +738,7 @@ void tomoyo_get_attributes(struct tomoyo_obj_info *obj) | |||
| 718 | inode = d_backing_inode(dentry); | 738 | inode = d_backing_inode(dentry); |
| 719 | if (inode) { | 739 | if (inode) { |
| 720 | struct tomoyo_mini_stat *stat = &obj->stat[i]; | 740 | struct tomoyo_mini_stat *stat = &obj->stat[i]; |
| 741 | |||
| 721 | stat->uid = inode->i_uid; | 742 | stat->uid = inode->i_uid; |
| 722 | stat->gid = inode->i_gid; | 743 | stat->gid = inode->i_gid; |
| 723 | stat->ino = inode->i_ino; | 744 | stat->ino = inode->i_ino; |
| @@ -726,8 +747,7 @@ void tomoyo_get_attributes(struct tomoyo_obj_info *obj) | |||
| 726 | stat->rdev = inode->i_rdev; | 747 | stat->rdev = inode->i_rdev; |
| 727 | obj->stat_valid[i] = true; | 748 | obj->stat_valid[i] = true; |
| 728 | } | 749 | } |
| 729 | if (i & 1) /* i == TOMOYO_PATH1_PARENT || | 750 | if (i & 1) /* TOMOYO_PATH1_PARENT or TOMOYO_PATH2_PARENT */ |
| 730 | i == TOMOYO_PATH2_PARENT */ | ||
| 731 | dput(dentry); | 751 | dput(dentry); |
| 732 | } | 752 | } |
| 733 | } | 753 | } |
| @@ -758,6 +778,7 @@ bool tomoyo_condition(struct tomoyo_request_info *r, | |||
| 758 | u16 argc; | 778 | u16 argc; |
| 759 | u16 envc; | 779 | u16 envc; |
| 760 | struct linux_binprm *bprm = NULL; | 780 | struct linux_binprm *bprm = NULL; |
| 781 | |||
| 761 | if (!cond) | 782 | if (!cond) |
| 762 | return true; | 783 | return true; |
| 763 | condc = cond->condc; | 784 | condc = cond->condc; |
| @@ -780,6 +801,7 @@ bool tomoyo_condition(struct tomoyo_request_info *r, | |||
| 780 | const u8 right = condp->right; | 801 | const u8 right = condp->right; |
| 781 | bool is_bitop[2] = { false, false }; | 802 | bool is_bitop[2] = { false, false }; |
| 782 | u8 j; | 803 | u8 j; |
| 804 | |||
| 783 | condp++; | 805 | condp++; |
| 784 | /* Check argv[] and envp[] later. */ | 806 | /* Check argv[] and envp[] later. */ |
| 785 | if (left == TOMOYO_ARGV_ENTRY || left == TOMOYO_ENVP_ENTRY) | 807 | if (left == TOMOYO_ARGV_ENTRY || left == TOMOYO_ENVP_ENTRY) |
| @@ -787,10 +809,11 @@ bool tomoyo_condition(struct tomoyo_request_info *r, | |||
| 787 | /* Check string expressions. */ | 809 | /* Check string expressions. */ |
| 788 | if (right == TOMOYO_NAME_UNION) { | 810 | if (right == TOMOYO_NAME_UNION) { |
| 789 | const struct tomoyo_name_union *ptr = names_p++; | 811 | const struct tomoyo_name_union *ptr = names_p++; |
| 812 | struct tomoyo_path_info *symlink; | ||
| 813 | struct tomoyo_execve *ee; | ||
| 814 | struct file *file; | ||
| 815 | |||
| 790 | switch (left) { | 816 | switch (left) { |
| 791 | struct tomoyo_path_info *symlink; | ||
| 792 | struct tomoyo_execve *ee; | ||
| 793 | struct file *file; | ||
| 794 | case TOMOYO_SYMLINK_TARGET: | 817 | case TOMOYO_SYMLINK_TARGET: |
| 795 | symlink = obj ? obj->symlink_target : NULL; | 818 | symlink = obj ? obj->symlink_target : NULL; |
| 796 | if (!symlink || | 819 | if (!symlink || |
| @@ -812,6 +835,7 @@ bool tomoyo_condition(struct tomoyo_request_info *r, | |||
| 812 | for (j = 0; j < 2; j++) { | 835 | for (j = 0; j < 2; j++) { |
| 813 | const u8 index = j ? right : left; | 836 | const u8 index = j ? right : left; |
| 814 | unsigned long value = 0; | 837 | unsigned long value = 0; |
| 838 | |||
| 815 | switch (index) { | 839 | switch (index) { |
| 816 | case TOMOYO_TASK_UID: | 840 | case TOMOYO_TASK_UID: |
| 817 | value = from_kuid(&init_user_ns, current_uid()); | 841 | value = from_kuid(&init_user_ns, current_uid()); |
| @@ -874,31 +898,31 @@ bool tomoyo_condition(struct tomoyo_request_info *r, | |||
| 874 | value = S_ISVTX; | 898 | value = S_ISVTX; |
| 875 | break; | 899 | break; |
| 876 | case TOMOYO_MODE_OWNER_READ: | 900 | case TOMOYO_MODE_OWNER_READ: |
| 877 | value = S_IRUSR; | 901 | value = 0400; |
| 878 | break; | 902 | break; |
| 879 | case TOMOYO_MODE_OWNER_WRITE: | 903 | case TOMOYO_MODE_OWNER_WRITE: |
| 880 | value = S_IWUSR; | 904 | value = 0200; |
| 881 | break; | 905 | break; |
| 882 | case TOMOYO_MODE_OWNER_EXECUTE: | 906 | case TOMOYO_MODE_OWNER_EXECUTE: |
| 883 | value = S_IXUSR; | 907 | value = 0100; |
| 884 | break; | 908 | break; |
| 885 | case TOMOYO_MODE_GROUP_READ: | 909 | case TOMOYO_MODE_GROUP_READ: |
| 886 | value = S_IRGRP; | 910 | value = 0040; |
| 887 | break; | 911 | break; |
| 888 | case TOMOYO_MODE_GROUP_WRITE: | 912 | case TOMOYO_MODE_GROUP_WRITE: |
| 889 | value = S_IWGRP; | 913 | value = 0020; |
| 890 | break; | 914 | break; |
| 891 | case TOMOYO_MODE_GROUP_EXECUTE: | 915 | case TOMOYO_MODE_GROUP_EXECUTE: |
| 892 | value = S_IXGRP; | 916 | value = 0010; |
| 893 | break; | 917 | break; |
| 894 | case TOMOYO_MODE_OTHERS_READ: | 918 | case TOMOYO_MODE_OTHERS_READ: |
| 895 | value = S_IROTH; | 919 | value = 0004; |
| 896 | break; | 920 | break; |
| 897 | case TOMOYO_MODE_OTHERS_WRITE: | 921 | case TOMOYO_MODE_OTHERS_WRITE: |
| 898 | value = S_IWOTH; | 922 | value = 0002; |
| 899 | break; | 923 | break; |
| 900 | case TOMOYO_MODE_OTHERS_EXECUTE: | 924 | case TOMOYO_MODE_OTHERS_EXECUTE: |
| 901 | value = S_IXOTH; | 925 | value = 0001; |
| 902 | break; | 926 | break; |
| 903 | case TOMOYO_EXEC_ARGC: | 927 | case TOMOYO_EXEC_ARGC: |
| 904 | if (!bprm) | 928 | if (!bprm) |
| @@ -923,6 +947,7 @@ bool tomoyo_condition(struct tomoyo_request_info *r, | |||
| 923 | { | 947 | { |
| 924 | u8 stat_index; | 948 | u8 stat_index; |
| 925 | struct tomoyo_mini_stat *stat; | 949 | struct tomoyo_mini_stat *stat; |
| 950 | |||
| 926 | switch (index) { | 951 | switch (index) { |
| 927 | case TOMOYO_PATH1_UID: | 952 | case TOMOYO_PATH1_UID: |
| 928 | case TOMOYO_PATH1_GID: | 953 | case TOMOYO_PATH1_GID: |
| @@ -1036,12 +1061,14 @@ bool tomoyo_condition(struct tomoyo_request_info *r, | |||
| 1036 | if (left == TOMOYO_NUMBER_UNION) { | 1061 | if (left == TOMOYO_NUMBER_UNION) { |
| 1037 | /* Fetch values now. */ | 1062 | /* Fetch values now. */ |
| 1038 | const struct tomoyo_number_union *ptr = numbers_p++; | 1063 | const struct tomoyo_number_union *ptr = numbers_p++; |
| 1064 | |||
| 1039 | min_v[0] = ptr->values[0]; | 1065 | min_v[0] = ptr->values[0]; |
| 1040 | max_v[0] = ptr->values[1]; | 1066 | max_v[0] = ptr->values[1]; |
| 1041 | } | 1067 | } |
| 1042 | if (right == TOMOYO_NUMBER_UNION) { | 1068 | if (right == TOMOYO_NUMBER_UNION) { |
| 1043 | /* Fetch values now. */ | 1069 | /* Fetch values now. */ |
| 1044 | const struct tomoyo_number_union *ptr = numbers_p++; | 1070 | const struct tomoyo_number_union *ptr = numbers_p++; |
| 1071 | |||
| 1045 | if (ptr->group) { | 1072 | if (ptr->group) { |
| 1046 | if (tomoyo_number_matches_group(min_v[0], | 1073 | if (tomoyo_number_matches_group(min_v[0], |
| 1047 | max_v[0], | 1074 | max_v[0], |
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index f6758dad981f..8526a0a74023 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
| @@ -30,10 +30,10 @@ struct tomoyo_domain_info tomoyo_kernel_domain; | |||
| 30 | */ | 30 | */ |
| 31 | int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, | 31 | int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, |
| 32 | struct tomoyo_acl_param *param, | 32 | struct tomoyo_acl_param *param, |
| 33 | bool (*check_duplicate) (const struct tomoyo_acl_head | 33 | bool (*check_duplicate)(const struct tomoyo_acl_head |
| 34 | *, | 34 | *, |
| 35 | const struct tomoyo_acl_head | 35 | const struct tomoyo_acl_head |
| 36 | *)) | 36 | *)) |
| 37 | { | 37 | { |
| 38 | int error = param->is_delete ? -ENOENT : -ENOMEM; | 38 | int error = param->is_delete ? -ENOENT : -ENOMEM; |
| 39 | struct tomoyo_acl_head *entry; | 39 | struct tomoyo_acl_head *entry; |
| @@ -90,13 +90,13 @@ static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a, | |||
| 90 | */ | 90 | */ |
| 91 | int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, | 91 | int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, |
| 92 | struct tomoyo_acl_param *param, | 92 | struct tomoyo_acl_param *param, |
| 93 | bool (*check_duplicate) (const struct tomoyo_acl_info | 93 | bool (*check_duplicate)(const struct tomoyo_acl_info |
| 94 | *, | 94 | *, |
| 95 | const struct tomoyo_acl_info | 95 | const struct tomoyo_acl_info |
| 96 | *), | 96 | *), |
| 97 | bool (*merge_duplicate) (struct tomoyo_acl_info *, | 97 | bool (*merge_duplicate)(struct tomoyo_acl_info *, |
| 98 | struct tomoyo_acl_info *, | 98 | struct tomoyo_acl_info *, |
| 99 | const bool)) | 99 | const bool)) |
| 100 | { | 100 | { |
| 101 | const bool is_delete = param->is_delete; | 101 | const bool is_delete = param->is_delete; |
| 102 | int error = is_delete ? -ENOENT : -ENOMEM; | 102 | int error = is_delete ? -ENOENT : -ENOMEM; |
| @@ -157,13 +157,13 @@ out: | |||
| 157 | * Caller holds tomoyo_read_lock(). | 157 | * Caller holds tomoyo_read_lock(). |
| 158 | */ | 158 | */ |
| 159 | void tomoyo_check_acl(struct tomoyo_request_info *r, | 159 | void tomoyo_check_acl(struct tomoyo_request_info *r, |
| 160 | bool (*check_entry) (struct tomoyo_request_info *, | 160 | bool (*check_entry)(struct tomoyo_request_info *, |
| 161 | const struct tomoyo_acl_info *)) | 161 | const struct tomoyo_acl_info *)) |
| 162 | { | 162 | { |
| 163 | const struct tomoyo_domain_info *domain = r->domain; | 163 | const struct tomoyo_domain_info *domain = r->domain; |
| 164 | struct tomoyo_acl_info *ptr; | 164 | struct tomoyo_acl_info *ptr; |
| 165 | bool retried = false; | ||
| 166 | const struct list_head *list = &domain->acl_info_list; | 165 | const struct list_head *list = &domain->acl_info_list; |
| 166 | u16 i = 0; | ||
| 167 | 167 | ||
| 168 | retry: | 168 | retry: |
| 169 | list_for_each_entry_rcu(ptr, list, list) { | 169 | list_for_each_entry_rcu(ptr, list, list) { |
| @@ -177,9 +177,10 @@ retry: | |||
| 177 | r->granted = true; | 177 | r->granted = true; |
| 178 | return; | 178 | return; |
| 179 | } | 179 | } |
| 180 | if (!retried) { | 180 | for (; i < TOMOYO_MAX_ACL_GROUPS; i++) { |
| 181 | retried = true; | 181 | if (!test_bit(i, domain->group)) |
| 182 | list = &domain->ns->acl_group[domain->group]; | 182 | continue; |
| 183 | list = &domain->ns->acl_group[i++]; | ||
| 183 | goto retry; | 184 | goto retry; |
| 184 | } | 185 | } |
| 185 | r->granted = false; | 186 | r->granted = false; |
| @@ -198,6 +199,7 @@ LIST_HEAD(tomoyo_domain_list); | |||
| 198 | static const char *tomoyo_last_word(const char *name) | 199 | static const char *tomoyo_last_word(const char *name) |
| 199 | { | 200 | { |
| 200 | const char *cp = strrchr(name, ' '); | 201 | const char *cp = strrchr(name, ' '); |
| 202 | |||
| 201 | if (cp) | 203 | if (cp) |
| 202 | return cp + 1; | 204 | return cp + 1; |
| 203 | return name; | 205 | return name; |
| @@ -220,6 +222,7 @@ static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a, | |||
| 220 | const struct tomoyo_transition_control *p2 = container_of(b, | 222 | const struct tomoyo_transition_control *p2 = container_of(b, |
| 221 | typeof(*p2), | 223 | typeof(*p2), |
| 222 | head); | 224 | head); |
| 225 | |||
| 223 | return p1->type == p2->type && p1->is_last_name == p2->is_last_name | 226 | return p1->type == p2->type && p1->is_last_name == p2->is_last_name |
| 224 | && p1->domainname == p2->domainname | 227 | && p1->domainname == p2->domainname |
| 225 | && p1->program == p2->program; | 228 | && p1->program == p2->program; |
| @@ -240,6 +243,7 @@ int tomoyo_write_transition_control(struct tomoyo_acl_param *param, | |||
| 240 | int error = param->is_delete ? -ENOENT : -ENOMEM; | 243 | int error = param->is_delete ? -ENOENT : -ENOMEM; |
| 241 | char *program = param->data; | 244 | char *program = param->data; |
| 242 | char *domainname = strstr(program, " from "); | 245 | char *domainname = strstr(program, " from "); |
| 246 | |||
| 243 | if (domainname) { | 247 | if (domainname) { |
| 244 | *domainname = '\0'; | 248 | *domainname = '\0'; |
| 245 | domainname += 6; | 249 | domainname += 6; |
| @@ -293,6 +297,7 @@ static inline bool tomoyo_scan_transition | |||
| 293 | const enum tomoyo_transition_type type) | 297 | const enum tomoyo_transition_type type) |
| 294 | { | 298 | { |
| 295 | const struct tomoyo_transition_control *ptr; | 299 | const struct tomoyo_transition_control *ptr; |
| 300 | |||
| 296 | list_for_each_entry_rcu(ptr, list, head.list) { | 301 | list_for_each_entry_rcu(ptr, list, head.list) { |
| 297 | if (ptr->head.is_deleted || ptr->type != type) | 302 | if (ptr->head.is_deleted || ptr->type != type) |
| 298 | continue; | 303 | continue; |
| @@ -338,9 +343,11 @@ static enum tomoyo_transition_type tomoyo_transition_type | |||
| 338 | { | 343 | { |
| 339 | const char *last_name = tomoyo_last_word(domainname->name); | 344 | const char *last_name = tomoyo_last_word(domainname->name); |
| 340 | enum tomoyo_transition_type type = TOMOYO_TRANSITION_CONTROL_NO_RESET; | 345 | enum tomoyo_transition_type type = TOMOYO_TRANSITION_CONTROL_NO_RESET; |
| 346 | |||
| 341 | while (type < TOMOYO_MAX_TRANSITION_TYPE) { | 347 | while (type < TOMOYO_MAX_TRANSITION_TYPE) { |
| 342 | const struct list_head * const list = | 348 | const struct list_head * const list = |
| 343 | &ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL]; | 349 | &ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL]; |
| 350 | |||
| 344 | if (!tomoyo_scan_transition(list, domainname, program, | 351 | if (!tomoyo_scan_transition(list, domainname, program, |
| 345 | last_name, type)) { | 352 | last_name, type)) { |
| 346 | type++; | 353 | type++; |
| @@ -375,6 +382,7 @@ static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a, | |||
| 375 | head); | 382 | head); |
| 376 | const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2), | 383 | const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2), |
| 377 | head); | 384 | head); |
| 385 | |||
| 378 | return p1->original_name == p2->original_name && | 386 | return p1->original_name == p2->original_name && |
| 379 | p1->aggregated_name == p2->aggregated_name; | 387 | p1->aggregated_name == p2->aggregated_name; |
| 380 | } | 388 | } |
| @@ -394,6 +402,7 @@ int tomoyo_write_aggregator(struct tomoyo_acl_param *param) | |||
| 394 | int error = param->is_delete ? -ENOENT : -ENOMEM; | 402 | int error = param->is_delete ? -ENOENT : -ENOMEM; |
| 395 | const char *original_name = tomoyo_read_token(param); | 403 | const char *original_name = tomoyo_read_token(param); |
| 396 | const char *aggregated_name = tomoyo_read_token(param); | 404 | const char *aggregated_name = tomoyo_read_token(param); |
| 405 | |||
| 397 | if (!tomoyo_correct_word(original_name) || | 406 | if (!tomoyo_correct_word(original_name) || |
| 398 | !tomoyo_correct_path(aggregated_name)) | 407 | !tomoyo_correct_path(aggregated_name)) |
| 399 | return -EINVAL; | 408 | return -EINVAL; |
| @@ -426,6 +435,7 @@ static struct tomoyo_policy_namespace *tomoyo_find_namespace | |||
| 426 | (const char *name, const unsigned int len) | 435 | (const char *name, const unsigned int len) |
| 427 | { | 436 | { |
| 428 | struct tomoyo_policy_namespace *ns; | 437 | struct tomoyo_policy_namespace *ns; |
| 438 | |||
| 429 | list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) { | 439 | list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) { |
| 430 | if (strncmp(name, ns->name, len) || | 440 | if (strncmp(name, ns->name, len) || |
| 431 | (name[len] && name[len] != ' ')) | 441 | (name[len] && name[len] != ' ')) |
| @@ -451,6 +461,7 @@ struct tomoyo_policy_namespace *tomoyo_assign_namespace(const char *domainname) | |||
| 451 | struct tomoyo_policy_namespace *entry; | 461 | struct tomoyo_policy_namespace *entry; |
| 452 | const char *cp = domainname; | 462 | const char *cp = domainname; |
| 453 | unsigned int len = 0; | 463 | unsigned int len = 0; |
| 464 | |||
| 454 | while (*cp && *cp++ != ' ') | 465 | while (*cp && *cp++ != ' ') |
| 455 | len++; | 466 | len++; |
| 456 | ptr = tomoyo_find_namespace(domainname, len); | 467 | ptr = tomoyo_find_namespace(domainname, len); |
| @@ -466,6 +477,7 @@ struct tomoyo_policy_namespace *tomoyo_assign_namespace(const char *domainname) | |||
| 466 | ptr = tomoyo_find_namespace(domainname, len); | 477 | ptr = tomoyo_find_namespace(domainname, len); |
| 467 | if (!ptr && tomoyo_memory_ok(entry)) { | 478 | if (!ptr && tomoyo_memory_ok(entry)) { |
| 468 | char *name = (char *) (entry + 1); | 479 | char *name = (char *) (entry + 1); |
| 480 | |||
| 469 | ptr = entry; | 481 | ptr = entry; |
| 470 | memmove(name, domainname, len); | 482 | memmove(name, domainname, len); |
| 471 | name[len] = '\0'; | 483 | name[len] = '\0'; |
| @@ -490,6 +502,7 @@ static bool tomoyo_namespace_jump(const char *domainname) | |||
| 490 | { | 502 | { |
| 491 | const char *namespace = tomoyo_current_namespace()->name; | 503 | const char *namespace = tomoyo_current_namespace()->name; |
| 492 | const int len = strlen(namespace); | 504 | const int len = strlen(namespace); |
| 505 | |||
| 493 | return strncmp(domainname, namespace, len) || | 506 | return strncmp(domainname, namespace, len) || |
| 494 | (domainname[len] && domainname[len] != ' '); | 507 | (domainname[len] && domainname[len] != ' '); |
| 495 | } | 508 | } |
| @@ -510,6 +523,7 @@ struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, | |||
| 510 | struct tomoyo_domain_info e = { }; | 523 | struct tomoyo_domain_info e = { }; |
| 511 | struct tomoyo_domain_info *entry = tomoyo_find_domain(domainname); | 524 | struct tomoyo_domain_info *entry = tomoyo_find_domain(domainname); |
| 512 | bool created = false; | 525 | bool created = false; |
| 526 | |||
| 513 | if (entry) { | 527 | if (entry) { |
| 514 | if (transit) { | 528 | if (transit) { |
| 515 | /* | 529 | /* |
| @@ -546,8 +560,9 @@ struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, | |||
| 546 | */ | 560 | */ |
| 547 | if (transit) { | 561 | if (transit) { |
| 548 | const struct tomoyo_domain_info *domain = tomoyo_domain(); | 562 | const struct tomoyo_domain_info *domain = tomoyo_domain(); |
| 563 | |||
| 549 | e.profile = domain->profile; | 564 | e.profile = domain->profile; |
| 550 | e.group = domain->group; | 565 | memcpy(e.group, domain->group, sizeof(e.group)); |
| 551 | } | 566 | } |
| 552 | e.domainname = tomoyo_get_name(domainname); | 567 | e.domainname = tomoyo_get_name(domainname); |
| 553 | if (!e.domainname) | 568 | if (!e.domainname) |
| @@ -569,12 +584,17 @@ out: | |||
| 569 | if (entry && transit) { | 584 | if (entry && transit) { |
| 570 | if (created) { | 585 | if (created) { |
| 571 | struct tomoyo_request_info r; | 586 | struct tomoyo_request_info r; |
| 587 | int i; | ||
| 588 | |||
| 572 | tomoyo_init_request_info(&r, entry, | 589 | tomoyo_init_request_info(&r, entry, |
| 573 | TOMOYO_MAC_FILE_EXECUTE); | 590 | TOMOYO_MAC_FILE_EXECUTE); |
| 574 | r.granted = false; | 591 | r.granted = false; |
| 575 | tomoyo_write_log(&r, "use_profile %u\n", | 592 | tomoyo_write_log(&r, "use_profile %u\n", |
| 576 | entry->profile); | 593 | entry->profile); |
| 577 | tomoyo_write_log(&r, "use_group %u\n", entry->group); | 594 | for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++) |
| 595 | if (test_bit(i, entry->group)) | ||
| 596 | tomoyo_write_log(&r, "use_group %u\n", | ||
| 597 | i); | ||
| 578 | tomoyo_update_stat(TOMOYO_STAT_POLICY_UPDATES); | 598 | tomoyo_update_stat(TOMOYO_STAT_POLICY_UPDATES); |
| 579 | } | 599 | } |
| 580 | } | 600 | } |
| @@ -712,6 +732,7 @@ retry: | |||
| 712 | struct tomoyo_aggregator *ptr; | 732 | struct tomoyo_aggregator *ptr; |
| 713 | struct list_head *list = | 733 | struct list_head *list = |
| 714 | &old_domain->ns->policy_list[TOMOYO_ID_AGGREGATOR]; | 734 | &old_domain->ns->policy_list[TOMOYO_ID_AGGREGATOR]; |
| 735 | |||
| 715 | /* Check 'aggregator' directive. */ | 736 | /* Check 'aggregator' directive. */ |
| 716 | candidate = &exename; | 737 | candidate = &exename; |
| 717 | list_for_each_entry_rcu(ptr, list, head.list) { | 738 | list_for_each_entry_rcu(ptr, list, head.list) { |
| @@ -747,6 +768,7 @@ retry: | |||
| 747 | */ | 768 | */ |
| 748 | if (ee->transition) { | 769 | if (ee->transition) { |
| 749 | const char *domainname = ee->transition->name; | 770 | const char *domainname = ee->transition->name; |
| 771 | |||
| 750 | reject_on_transition_failure = true; | 772 | reject_on_transition_failure = true; |
| 751 | if (!strcmp(domainname, "keep")) | 773 | if (!strcmp(domainname, "keep")) |
| 752 | goto force_keep_domain; | 774 | goto force_keep_domain; |
| @@ -758,6 +780,7 @@ retry: | |||
| 758 | goto force_initialize_domain; | 780 | goto force_initialize_domain; |
| 759 | if (!strcmp(domainname, "parent")) { | 781 | if (!strcmp(domainname, "parent")) { |
| 760 | char *cp; | 782 | char *cp; |
| 783 | |||
| 761 | strncpy(ee->tmp, old_domain->domainname->name, | 784 | strncpy(ee->tmp, old_domain->domainname->name, |
| 762 | TOMOYO_EXEC_TMPSIZE - 1); | 785 | TOMOYO_EXEC_TMPSIZE - 1); |
| 763 | cp = strrchr(ee->tmp, ' '); | 786 | cp = strrchr(ee->tmp, ' '); |
| @@ -822,8 +845,7 @@ force_jump_domain: | |||
| 822 | if (domain) | 845 | if (domain) |
| 823 | retval = 0; | 846 | retval = 0; |
| 824 | else if (reject_on_transition_failure) { | 847 | else if (reject_on_transition_failure) { |
| 825 | printk(KERN_WARNING "ERROR: Domain '%s' not ready.\n", | 848 | pr_warn("ERROR: Domain '%s' not ready.\n", ee->tmp); |
| 826 | ee->tmp); | ||
| 827 | retval = -ENOMEM; | 849 | retval = -ENOMEM; |
| 828 | } else if (ee->r.mode == TOMOYO_CONFIG_ENFORCING) | 850 | } else if (ee->r.mode == TOMOYO_CONFIG_ENFORCING) |
| 829 | retval = -ENOMEM; | 851 | retval = -ENOMEM; |
| @@ -834,16 +856,20 @@ force_jump_domain: | |||
| 834 | ee->r.granted = false; | 856 | ee->r.granted = false; |
| 835 | tomoyo_write_log(&ee->r, "%s", tomoyo_dif | 857 | tomoyo_write_log(&ee->r, "%s", tomoyo_dif |
| 836 | [TOMOYO_DIF_TRANSITION_FAILED]); | 858 | [TOMOYO_DIF_TRANSITION_FAILED]); |
| 837 | printk(KERN_WARNING | 859 | pr_warn("ERROR: Domain '%s' not defined.\n", ee->tmp); |
| 838 | "ERROR: Domain '%s' not defined.\n", ee->tmp); | ||
| 839 | } | 860 | } |
| 840 | } | 861 | } |
| 841 | out: | 862 | out: |
| 842 | if (!domain) | 863 | if (!domain) |
| 843 | domain = old_domain; | 864 | domain = old_domain; |
| 844 | /* Update reference count on "struct tomoyo_domain_info". */ | 865 | /* Update reference count on "struct tomoyo_domain_info". */ |
| 845 | atomic_inc(&domain->users); | 866 | { |
| 846 | bprm->cred->security = domain; | 867 | struct tomoyo_task *s = tomoyo_task(current); |
| 868 | |||
| 869 | s->old_domain_info = s->domain_info; | ||
| 870 | s->domain_info = domain; | ||
| 871 | atomic_inc(&domain->users); | ||
| 872 | } | ||
| 847 | kfree(exename.name); | 873 | kfree(exename.name); |
| 848 | if (!retval) { | 874 | if (!retval) { |
| 849 | ee->r.domain = domain; | 875 | ee->r.domain = domain; |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 2a374b4da8f5..86f7d1b90212 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
| @@ -214,6 +214,7 @@ static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r) | |||
| 214 | const u8 type = r->param.path_number.operation; | 214 | const u8 type = r->param.path_number.operation; |
| 215 | u8 radix; | 215 | u8 radix; |
| 216 | char buffer[64]; | 216 | char buffer[64]; |
| 217 | |||
| 217 | switch (type) { | 218 | switch (type) { |
| 218 | case TOMOYO_TYPE_CREATE: | 219 | case TOMOYO_TYPE_CREATE: |
| 219 | case TOMOYO_TYPE_MKDIR: | 220 | case TOMOYO_TYPE_MKDIR: |
| @@ -253,6 +254,7 @@ static bool tomoyo_check_path_acl(struct tomoyo_request_info *r, | |||
| 253 | { | 254 | { |
| 254 | const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl), | 255 | const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl), |
| 255 | head); | 256 | head); |
| 257 | |||
| 256 | if (acl->perm & (1 << r->param.path.operation)) { | 258 | if (acl->perm & (1 << r->param.path.operation)) { |
| 257 | r->param.path.matched_path = | 259 | r->param.path.matched_path = |
| 258 | tomoyo_compare_name_union(r->param.path.filename, | 260 | tomoyo_compare_name_union(r->param.path.filename, |
| @@ -275,6 +277,7 @@ static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r, | |||
| 275 | { | 277 | { |
| 276 | const struct tomoyo_path_number_acl *acl = | 278 | const struct tomoyo_path_number_acl *acl = |
| 277 | container_of(ptr, typeof(*acl), head); | 279 | container_of(ptr, typeof(*acl), head); |
| 280 | |||
| 278 | return (acl->perm & (1 << r->param.path_number.operation)) && | 281 | return (acl->perm & (1 << r->param.path_number.operation)) && |
| 279 | tomoyo_compare_number_union(r->param.path_number.number, | 282 | tomoyo_compare_number_union(r->param.path_number.number, |
| 280 | &acl->number) && | 283 | &acl->number) && |
| @@ -295,6 +298,7 @@ static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r, | |||
| 295 | { | 298 | { |
| 296 | const struct tomoyo_path2_acl *acl = | 299 | const struct tomoyo_path2_acl *acl = |
| 297 | container_of(ptr, typeof(*acl), head); | 300 | container_of(ptr, typeof(*acl), head); |
| 301 | |||
| 298 | return (acl->perm & (1 << r->param.path2.operation)) && | 302 | return (acl->perm & (1 << r->param.path2.operation)) && |
| 299 | tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1) | 303 | tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1) |
| 300 | && tomoyo_compare_name_union(r->param.path2.filename2, | 304 | && tomoyo_compare_name_union(r->param.path2.filename2, |
| @@ -314,6 +318,7 @@ static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r, | |||
| 314 | { | 318 | { |
| 315 | const struct tomoyo_mkdev_acl *acl = | 319 | const struct tomoyo_mkdev_acl *acl = |
| 316 | container_of(ptr, typeof(*acl), head); | 320 | container_of(ptr, typeof(*acl), head); |
| 321 | |||
| 317 | return (acl->perm & (1 << r->param.mkdev.operation)) && | 322 | return (acl->perm & (1 << r->param.mkdev.operation)) && |
| 318 | tomoyo_compare_number_union(r->param.mkdev.mode, | 323 | tomoyo_compare_number_union(r->param.mkdev.mode, |
| 319 | &acl->mode) && | 324 | &acl->mode) && |
| @@ -338,6 +343,7 @@ static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a, | |||
| 338 | { | 343 | { |
| 339 | const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head); | 344 | const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head); |
| 340 | const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head); | 345 | const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head); |
| 346 | |||
| 341 | return tomoyo_same_name_union(&p1->name, &p2->name); | 347 | return tomoyo_same_name_union(&p1->name, &p2->name); |
| 342 | } | 348 | } |
| 343 | 349 | ||
| @@ -358,6 +364,7 @@ static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a, | |||
| 358 | ->perm; | 364 | ->perm; |
| 359 | u16 perm = *a_perm; | 365 | u16 perm = *a_perm; |
| 360 | const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm; | 366 | const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm; |
| 367 | |||
| 361 | if (is_delete) | 368 | if (is_delete) |
| 362 | perm &= ~b_perm; | 369 | perm &= ~b_perm; |
| 363 | else | 370 | else |
| @@ -384,6 +391,7 @@ static int tomoyo_update_path_acl(const u16 perm, | |||
| 384 | .perm = perm | 391 | .perm = perm |
| 385 | }; | 392 | }; |
| 386 | int error; | 393 | int error; |
| 394 | |||
| 387 | if (!tomoyo_parse_name_union(param, &e.name)) | 395 | if (!tomoyo_parse_name_union(param, &e.name)) |
| 388 | error = -EINVAL; | 396 | error = -EINVAL; |
| 389 | else | 397 | else |
| @@ -407,6 +415,7 @@ static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a, | |||
| 407 | { | 415 | { |
| 408 | const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head); | 416 | const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head); |
| 409 | const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head); | 417 | const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head); |
| 418 | |||
| 410 | return tomoyo_same_name_union(&p1->name, &p2->name) && | 419 | return tomoyo_same_name_union(&p1->name, &p2->name) && |
| 411 | tomoyo_same_number_union(&p1->mode, &p2->mode) && | 420 | tomoyo_same_number_union(&p1->mode, &p2->mode) && |
| 412 | tomoyo_same_number_union(&p1->major, &p2->major) && | 421 | tomoyo_same_number_union(&p1->major, &p2->major) && |
| @@ -431,6 +440,7 @@ static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a, | |||
| 431 | u8 perm = *a_perm; | 440 | u8 perm = *a_perm; |
| 432 | const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head) | 441 | const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head) |
| 433 | ->perm; | 442 | ->perm; |
| 443 | |||
| 434 | if (is_delete) | 444 | if (is_delete) |
| 435 | perm &= ~b_perm; | 445 | perm &= ~b_perm; |
| 436 | else | 446 | else |
| @@ -457,6 +467,7 @@ static int tomoyo_update_mkdev_acl(const u8 perm, | |||
| 457 | .perm = perm | 467 | .perm = perm |
| 458 | }; | 468 | }; |
| 459 | int error; | 469 | int error; |
| 470 | |||
| 460 | if (!tomoyo_parse_name_union(param, &e.name) || | 471 | if (!tomoyo_parse_name_union(param, &e.name) || |
| 461 | !tomoyo_parse_number_union(param, &e.mode) || | 472 | !tomoyo_parse_number_union(param, &e.mode) || |
| 462 | !tomoyo_parse_number_union(param, &e.major) || | 473 | !tomoyo_parse_number_union(param, &e.major) || |
| @@ -486,6 +497,7 @@ static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a, | |||
| 486 | { | 497 | { |
| 487 | const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head); | 498 | const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head); |
| 488 | const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head); | 499 | const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head); |
| 500 | |||
| 489 | return tomoyo_same_name_union(&p1->name1, &p2->name1) && | 501 | return tomoyo_same_name_union(&p1->name1, &p2->name1) && |
| 490 | tomoyo_same_name_union(&p1->name2, &p2->name2); | 502 | tomoyo_same_name_union(&p1->name2, &p2->name2); |
| 491 | } | 503 | } |
| @@ -507,6 +519,7 @@ static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a, | |||
| 507 | ->perm; | 519 | ->perm; |
| 508 | u8 perm = *a_perm; | 520 | u8 perm = *a_perm; |
| 509 | const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm; | 521 | const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm; |
| 522 | |||
| 510 | if (is_delete) | 523 | if (is_delete) |
| 511 | perm &= ~b_perm; | 524 | perm &= ~b_perm; |
| 512 | else | 525 | else |
| @@ -533,6 +546,7 @@ static int tomoyo_update_path2_acl(const u8 perm, | |||
| 533 | .perm = perm | 546 | .perm = perm |
| 534 | }; | 547 | }; |
| 535 | int error; | 548 | int error; |
| 549 | |||
| 536 | if (!tomoyo_parse_name_union(param, &e.name1) || | 550 | if (!tomoyo_parse_name_union(param, &e.name1) || |
| 537 | !tomoyo_parse_name_union(param, &e.name2)) | 551 | !tomoyo_parse_name_union(param, &e.name2)) |
| 538 | error = -EINVAL; | 552 | error = -EINVAL; |
| @@ -621,6 +635,7 @@ static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a, | |||
| 621 | head); | 635 | head); |
| 622 | const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2), | 636 | const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2), |
| 623 | head); | 637 | head); |
| 638 | |||
| 624 | return tomoyo_same_name_union(&p1->name, &p2->name) && | 639 | return tomoyo_same_name_union(&p1->name, &p2->name) && |
| 625 | tomoyo_same_number_union(&p1->number, &p2->number); | 640 | tomoyo_same_number_union(&p1->number, &p2->number); |
| 626 | } | 641 | } |
| @@ -643,6 +658,7 @@ static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a, | |||
| 643 | u8 perm = *a_perm; | 658 | u8 perm = *a_perm; |
| 644 | const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head) | 659 | const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head) |
| 645 | ->perm; | 660 | ->perm; |
| 661 | |||
| 646 | if (is_delete) | 662 | if (is_delete) |
| 647 | perm &= ~b_perm; | 663 | perm &= ~b_perm; |
| 648 | else | 664 | else |
| @@ -667,6 +683,7 @@ static int tomoyo_update_path_number_acl(const u8 perm, | |||
| 667 | .perm = perm | 683 | .perm = perm |
| 668 | }; | 684 | }; |
| 669 | int error; | 685 | int error; |
| 686 | |||
| 670 | if (!tomoyo_parse_name_union(param, &e.name) || | 687 | if (!tomoyo_parse_name_union(param, &e.name) || |
| 671 | !tomoyo_parse_number_union(param, &e.number)) | 688 | !tomoyo_parse_number_union(param, &e.number)) |
| 672 | error = -EINVAL; | 689 | error = -EINVAL; |
| @@ -947,6 +964,7 @@ static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a, | |||
| 947 | { | 964 | { |
| 948 | const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head); | 965 | const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head); |
| 949 | const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head); | 966 | const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head); |
| 967 | |||
| 950 | return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) && | 968 | return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) && |
| 951 | tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) && | 969 | tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) && |
| 952 | tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) && | 970 | tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) && |
| @@ -966,6 +984,7 @@ static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param) | |||
| 966 | { | 984 | { |
| 967 | struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL }; | 985 | struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL }; |
| 968 | int error; | 986 | int error; |
| 987 | |||
| 969 | if (!tomoyo_parse_name_union(param, &e.dev_name) || | 988 | if (!tomoyo_parse_name_union(param, &e.dev_name) || |
| 970 | !tomoyo_parse_name_union(param, &e.dir_name) || | 989 | !tomoyo_parse_name_union(param, &e.dir_name) || |
| 971 | !tomoyo_parse_name_union(param, &e.fs_type) || | 990 | !tomoyo_parse_name_union(param, &e.fs_type) || |
| @@ -995,6 +1014,7 @@ int tomoyo_write_file(struct tomoyo_acl_param *param) | |||
| 995 | u16 perm = 0; | 1014 | u16 perm = 0; |
| 996 | u8 type; | 1015 | u8 type; |
| 997 | const char *operation = tomoyo_read_token(param); | 1016 | const char *operation = tomoyo_read_token(param); |
| 1017 | |||
| 998 | for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) | 1018 | for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) |
| 999 | if (tomoyo_permstr(operation, tomoyo_path_keyword[type])) | 1019 | if (tomoyo_permstr(operation, tomoyo_path_keyword[type])) |
| 1000 | perm |= 1 << type; | 1020 | perm |= 1 << type; |
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index e22bea811c57..9537832fca18 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c | |||
| @@ -77,11 +77,13 @@ static bool tomoyo_name_used_by_io_buffer(const char *string) | |||
| 77 | spin_lock(&tomoyo_io_buffer_list_lock); | 77 | spin_lock(&tomoyo_io_buffer_list_lock); |
| 78 | list_for_each_entry(head, &tomoyo_io_buffer_list, list) { | 78 | list_for_each_entry(head, &tomoyo_io_buffer_list, list) { |
| 79 | int i; | 79 | int i; |
| 80 | |||
| 80 | head->users++; | 81 | head->users++; |
| 81 | spin_unlock(&tomoyo_io_buffer_list_lock); | 82 | spin_unlock(&tomoyo_io_buffer_list_lock); |
| 82 | mutex_lock(&head->io_sem); | 83 | mutex_lock(&head->io_sem); |
| 83 | for (i = 0; i < TOMOYO_MAX_IO_READ_QUEUE; i++) { | 84 | for (i = 0; i < TOMOYO_MAX_IO_READ_QUEUE; i++) { |
| 84 | const char *w = head->r.w[i]; | 85 | const char *w = head->r.w[i]; |
| 86 | |||
| 85 | if (w < string || w > string + size) | 87 | if (w < string || w > string + size) |
| 86 | continue; | 88 | continue; |
| 87 | in_use = true; | 89 | in_use = true; |
| @@ -108,6 +110,7 @@ static inline void tomoyo_del_transition_control(struct list_head *element) | |||
| 108 | { | 110 | { |
| 109 | struct tomoyo_transition_control *ptr = | 111 | struct tomoyo_transition_control *ptr = |
| 110 | container_of(element, typeof(*ptr), head.list); | 112 | container_of(element, typeof(*ptr), head.list); |
| 113 | |||
| 111 | tomoyo_put_name(ptr->domainname); | 114 | tomoyo_put_name(ptr->domainname); |
| 112 | tomoyo_put_name(ptr->program); | 115 | tomoyo_put_name(ptr->program); |
| 113 | } | 116 | } |
| @@ -123,6 +126,7 @@ static inline void tomoyo_del_aggregator(struct list_head *element) | |||
| 123 | { | 126 | { |
| 124 | struct tomoyo_aggregator *ptr = | 127 | struct tomoyo_aggregator *ptr = |
| 125 | container_of(element, typeof(*ptr), head.list); | 128 | container_of(element, typeof(*ptr), head.list); |
| 129 | |||
| 126 | tomoyo_put_name(ptr->original_name); | 130 | tomoyo_put_name(ptr->original_name); |
| 127 | tomoyo_put_name(ptr->aggregated_name); | 131 | tomoyo_put_name(ptr->aggregated_name); |
| 128 | } | 132 | } |
| @@ -138,6 +142,7 @@ static inline void tomoyo_del_manager(struct list_head *element) | |||
| 138 | { | 142 | { |
| 139 | struct tomoyo_manager *ptr = | 143 | struct tomoyo_manager *ptr = |
| 140 | container_of(element, typeof(*ptr), head.list); | 144 | container_of(element, typeof(*ptr), head.list); |
| 145 | |||
| 141 | tomoyo_put_name(ptr->manager); | 146 | tomoyo_put_name(ptr->manager); |
| 142 | } | 147 | } |
| 143 | 148 | ||
| @@ -152,6 +157,7 @@ static void tomoyo_del_acl(struct list_head *element) | |||
| 152 | { | 157 | { |
| 153 | struct tomoyo_acl_info *acl = | 158 | struct tomoyo_acl_info *acl = |
| 154 | container_of(element, typeof(*acl), list); | 159 | container_of(element, typeof(*acl), list); |
| 160 | |||
| 155 | tomoyo_put_condition(acl->cond); | 161 | tomoyo_put_condition(acl->cond); |
| 156 | switch (acl->type) { | 162 | switch (acl->type) { |
| 157 | case TOMOYO_TYPE_PATH_ACL: | 163 | case TOMOYO_TYPE_PATH_ACL: |
| @@ -226,6 +232,7 @@ static void tomoyo_del_acl(struct list_head *element) | |||
| 226 | { | 232 | { |
| 227 | struct tomoyo_task_acl *entry = | 233 | struct tomoyo_task_acl *entry = |
| 228 | container_of(acl, typeof(*entry), head); | 234 | container_of(acl, typeof(*entry), head); |
| 235 | |||
| 229 | tomoyo_put_name(entry->domainname); | 236 | tomoyo_put_name(entry->domainname); |
| 230 | } | 237 | } |
| 231 | break; | 238 | break; |
| @@ -247,6 +254,7 @@ static inline void tomoyo_del_domain(struct list_head *element) | |||
| 247 | container_of(element, typeof(*domain), list); | 254 | container_of(element, typeof(*domain), list); |
| 248 | struct tomoyo_acl_info *acl; | 255 | struct tomoyo_acl_info *acl; |
| 249 | struct tomoyo_acl_info *tmp; | 256 | struct tomoyo_acl_info *tmp; |
| 257 | |||
| 250 | /* | 258 | /* |
| 251 | * Since this domain is referenced from neither | 259 | * Since this domain is referenced from neither |
| 252 | * "struct tomoyo_io_buffer" nor "struct cred"->security, we can delete | 260 | * "struct tomoyo_io_buffer" nor "struct cred"->security, we can delete |
| @@ -286,6 +294,7 @@ void tomoyo_del_condition(struct list_head *element) | |||
| 286 | = (const struct tomoyo_argv *) (names_p + names_count); | 294 | = (const struct tomoyo_argv *) (names_p + names_count); |
| 287 | const struct tomoyo_envp *envp | 295 | const struct tomoyo_envp *envp |
| 288 | = (const struct tomoyo_envp *) (argv + argc); | 296 | = (const struct tomoyo_envp *) (argv + argc); |
| 297 | |||
| 289 | for (i = 0; i < numbers_count; i++) | 298 | for (i = 0; i < numbers_count; i++) |
| 290 | tomoyo_put_number_union(numbers_p++); | 299 | tomoyo_put_number_union(numbers_p++); |
| 291 | for (i = 0; i < names_count; i++) | 300 | for (i = 0; i < names_count; i++) |
| @@ -321,6 +330,7 @@ static inline void tomoyo_del_path_group(struct list_head *element) | |||
| 321 | { | 330 | { |
| 322 | struct tomoyo_path_group *member = | 331 | struct tomoyo_path_group *member = |
| 323 | container_of(element, typeof(*member), head.list); | 332 | container_of(element, typeof(*member), head.list); |
| 333 | |||
| 324 | tomoyo_put_name(member->member_name); | 334 | tomoyo_put_name(member->member_name); |
| 325 | } | 335 | } |
| 326 | 336 | ||
| @@ -335,6 +345,7 @@ static inline void tomoyo_del_group(struct list_head *element) | |||
| 335 | { | 345 | { |
| 336 | struct tomoyo_group *group = | 346 | struct tomoyo_group *group = |
| 337 | container_of(element, typeof(*group), head.list); | 347 | container_of(element, typeof(*group), head.list); |
| 348 | |||
| 338 | tomoyo_put_name(group->group_name); | 349 | tomoyo_put_name(group->group_name); |
| 339 | } | 350 | } |
| 340 | 351 | ||
| @@ -476,6 +487,7 @@ static void tomoyo_collect_member(const enum tomoyo_policy_id id, | |||
| 476 | { | 487 | { |
| 477 | struct tomoyo_acl_head *member; | 488 | struct tomoyo_acl_head *member; |
| 478 | struct tomoyo_acl_head *tmp; | 489 | struct tomoyo_acl_head *tmp; |
| 490 | |||
| 479 | list_for_each_entry_safe(member, tmp, member_list, list) { | 491 | list_for_each_entry_safe(member, tmp, member_list, list) { |
| 480 | if (!member->is_deleted) | 492 | if (!member->is_deleted) |
| 481 | continue; | 493 | continue; |
| @@ -495,6 +507,7 @@ static void tomoyo_collect_acl(struct list_head *list) | |||
| 495 | { | 507 | { |
| 496 | struct tomoyo_acl_info *acl; | 508 | struct tomoyo_acl_info *acl; |
| 497 | struct tomoyo_acl_info *tmp; | 509 | struct tomoyo_acl_info *tmp; |
| 510 | |||
| 498 | list_for_each_entry_safe(acl, tmp, list, list) { | 511 | list_for_each_entry_safe(acl, tmp, list, list) { |
| 499 | if (!acl->is_deleted) | 512 | if (!acl->is_deleted) |
| 500 | continue; | 513 | continue; |
| @@ -513,10 +526,12 @@ static void tomoyo_collect_entry(void) | |||
| 513 | int i; | 526 | int i; |
| 514 | enum tomoyo_policy_id id; | 527 | enum tomoyo_policy_id id; |
| 515 | struct tomoyo_policy_namespace *ns; | 528 | struct tomoyo_policy_namespace *ns; |
| 529 | |||
| 516 | mutex_lock(&tomoyo_policy_lock); | 530 | mutex_lock(&tomoyo_policy_lock); |
| 517 | { | 531 | { |
| 518 | struct tomoyo_domain_info *domain; | 532 | struct tomoyo_domain_info *domain; |
| 519 | struct tomoyo_domain_info *tmp; | 533 | struct tomoyo_domain_info *tmp; |
| 534 | |||
| 520 | list_for_each_entry_safe(domain, tmp, &tomoyo_domain_list, | 535 | list_for_each_entry_safe(domain, tmp, &tomoyo_domain_list, |
| 521 | list) { | 536 | list) { |
| 522 | tomoyo_collect_acl(&domain->acl_info_list); | 537 | tomoyo_collect_acl(&domain->acl_info_list); |
| @@ -534,6 +549,7 @@ static void tomoyo_collect_entry(void) | |||
| 534 | { | 549 | { |
| 535 | struct tomoyo_shared_acl_head *ptr; | 550 | struct tomoyo_shared_acl_head *ptr; |
| 536 | struct tomoyo_shared_acl_head *tmp; | 551 | struct tomoyo_shared_acl_head *tmp; |
| 552 | |||
| 537 | list_for_each_entry_safe(ptr, tmp, &tomoyo_condition_list, | 553 | list_for_each_entry_safe(ptr, tmp, &tomoyo_condition_list, |
| 538 | list) { | 554 | list) { |
| 539 | if (atomic_read(&ptr->users) > 0) | 555 | if (atomic_read(&ptr->users) > 0) |
| @@ -547,6 +563,7 @@ static void tomoyo_collect_entry(void) | |||
| 547 | struct list_head *list = &ns->group_list[i]; | 563 | struct list_head *list = &ns->group_list[i]; |
| 548 | struct tomoyo_group *group; | 564 | struct tomoyo_group *group; |
| 549 | struct tomoyo_group *tmp; | 565 | struct tomoyo_group *tmp; |
| 566 | |||
| 550 | switch (i) { | 567 | switch (i) { |
| 551 | case 0: | 568 | case 0: |
| 552 | id = TOMOYO_ID_PATH_GROUP; | 569 | id = TOMOYO_ID_PATH_GROUP; |
| @@ -574,6 +591,7 @@ static void tomoyo_collect_entry(void) | |||
| 574 | struct list_head *list = &tomoyo_name_list[i]; | 591 | struct list_head *list = &tomoyo_name_list[i]; |
| 575 | struct tomoyo_shared_acl_head *ptr; | 592 | struct tomoyo_shared_acl_head *ptr; |
| 576 | struct tomoyo_shared_acl_head *tmp; | 593 | struct tomoyo_shared_acl_head *tmp; |
| 594 | |||
| 577 | list_for_each_entry_safe(ptr, tmp, list, list) { | 595 | list_for_each_entry_safe(ptr, tmp, list, list) { |
| 578 | if (atomic_read(&ptr->users) > 0) | 596 | if (atomic_read(&ptr->users) > 0) |
| 579 | continue; | 597 | continue; |
| @@ -595,6 +613,7 @@ static int tomoyo_gc_thread(void *unused) | |||
| 595 | { | 613 | { |
| 596 | /* Garbage collector thread is exclusive. */ | 614 | /* Garbage collector thread is exclusive. */ |
| 597 | static DEFINE_MUTEX(tomoyo_gc_mutex); | 615 | static DEFINE_MUTEX(tomoyo_gc_mutex); |
| 616 | |||
| 598 | if (!mutex_trylock(&tomoyo_gc_mutex)) | 617 | if (!mutex_trylock(&tomoyo_gc_mutex)) |
| 599 | goto out; | 618 | goto out; |
| 600 | tomoyo_collect_entry(); | 619 | tomoyo_collect_entry(); |
diff --git a/security/tomoyo/group.c b/security/tomoyo/group.c index 21b0cc3a7e1a..a37c7dc66e44 100644 --- a/security/tomoyo/group.c +++ b/security/tomoyo/group.c | |||
| @@ -75,11 +75,13 @@ int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type) | |||
| 75 | { | 75 | { |
| 76 | struct tomoyo_group *group = tomoyo_get_group(param, type); | 76 | struct tomoyo_group *group = tomoyo_get_group(param, type); |
| 77 | int error = -EINVAL; | 77 | int error = -EINVAL; |
| 78 | |||
| 78 | if (!group) | 79 | if (!group) |
| 79 | return -ENOMEM; | 80 | return -ENOMEM; |
| 80 | param->list = &group->member_list; | 81 | param->list = &group->member_list; |
| 81 | if (type == TOMOYO_PATH_GROUP) { | 82 | if (type == TOMOYO_PATH_GROUP) { |
| 82 | struct tomoyo_path_group e = { }; | 83 | struct tomoyo_path_group e = { }; |
| 84 | |||
| 83 | e.member_name = tomoyo_get_name(tomoyo_read_token(param)); | 85 | e.member_name = tomoyo_get_name(tomoyo_read_token(param)); |
| 84 | if (!e.member_name) { | 86 | if (!e.member_name) { |
| 85 | error = -ENOMEM; | 87 | error = -ENOMEM; |
| @@ -90,6 +92,7 @@ int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type) | |||
| 90 | tomoyo_put_name(e.member_name); | 92 | tomoyo_put_name(e.member_name); |
| 91 | } else if (type == TOMOYO_NUMBER_GROUP) { | 93 | } else if (type == TOMOYO_NUMBER_GROUP) { |
| 92 | struct tomoyo_number_group e = { }; | 94 | struct tomoyo_number_group e = { }; |
| 95 | |||
| 93 | if (param->data[0] == '@' || | 96 | if (param->data[0] == '@' || |
| 94 | !tomoyo_parse_number_union(param, &e.number)) | 97 | !tomoyo_parse_number_union(param, &e.number)) |
| 95 | goto out; | 98 | goto out; |
| @@ -129,6 +132,7 @@ tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, | |||
| 129 | const struct tomoyo_group *group) | 132 | const struct tomoyo_group *group) |
| 130 | { | 133 | { |
| 131 | struct tomoyo_path_group *member; | 134 | struct tomoyo_path_group *member; |
| 135 | |||
| 132 | list_for_each_entry_rcu(member, &group->member_list, head.list) { | 136 | list_for_each_entry_rcu(member, &group->member_list, head.list) { |
| 133 | if (member->head.is_deleted) | 137 | if (member->head.is_deleted) |
| 134 | continue; | 138 | continue; |
| @@ -156,6 +160,7 @@ bool tomoyo_number_matches_group(const unsigned long min, | |||
| 156 | { | 160 | { |
| 157 | struct tomoyo_number_group *member; | 161 | struct tomoyo_number_group *member; |
| 158 | bool matched = false; | 162 | bool matched = false; |
| 163 | |||
| 159 | list_for_each_entry_rcu(member, &group->member_list, head.list) { | 164 | list_for_each_entry_rcu(member, &group->member_list, head.list) { |
| 160 | if (member->head.is_deleted) | 165 | if (member->head.is_deleted) |
| 161 | continue; | 166 | continue; |
diff --git a/security/tomoyo/load_policy.c b/security/tomoyo/load_policy.c index 81b951652051..3445ae6fd479 100644 --- a/security/tomoyo/load_policy.c +++ b/security/tomoyo/load_policy.c | |||
| @@ -37,11 +37,12 @@ __setup("TOMOYO_loader=", tomoyo_loader_setup); | |||
| 37 | static bool tomoyo_policy_loader_exists(void) | 37 | static bool tomoyo_policy_loader_exists(void) |
| 38 | { | 38 | { |
| 39 | struct path path; | 39 | struct path path; |
| 40 | |||
| 40 | if (!tomoyo_loader) | 41 | if (!tomoyo_loader) |
| 41 | tomoyo_loader = CONFIG_SECURITY_TOMOYO_POLICY_LOADER; | 42 | tomoyo_loader = CONFIG_SECURITY_TOMOYO_POLICY_LOADER; |
| 42 | if (kern_path(tomoyo_loader, LOOKUP_FOLLOW, &path)) { | 43 | if (kern_path(tomoyo_loader, LOOKUP_FOLLOW, &path)) { |
| 43 | printk(KERN_INFO "Not activating Mandatory Access Control " | 44 | pr_info("Not activating Mandatory Access Control as %s does not exist.\n", |
| 44 | "as %s does not exist.\n", tomoyo_loader); | 45 | tomoyo_loader); |
| 45 | return false; | 46 | return false; |
| 46 | } | 47 | } |
| 47 | path_put(&path); | 48 | path_put(&path); |
| @@ -96,8 +97,7 @@ void tomoyo_load_policy(const char *filename) | |||
| 96 | if (!tomoyo_policy_loader_exists()) | 97 | if (!tomoyo_policy_loader_exists()) |
| 97 | return; | 98 | return; |
| 98 | done = true; | 99 | done = true; |
| 99 | printk(KERN_INFO "Calling %s to load policy. Please wait.\n", | 100 | pr_info("Calling %s to load policy. Please wait.\n", tomoyo_loader); |
| 100 | tomoyo_loader); | ||
| 101 | argv[0] = (char *) tomoyo_loader; | 101 | argv[0] = (char *) tomoyo_loader; |
| 102 | argv[1] = NULL; | 102 | argv[1] = NULL; |
| 103 | envp[0] = "HOME=/"; | 103 | envp[0] = "HOME=/"; |
diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c index 12477e0b0a11..2e7fcfa923c9 100644 --- a/security/tomoyo/memory.c +++ b/security/tomoyo/memory.c | |||
| @@ -19,9 +19,9 @@ void tomoyo_warn_oom(const char *function) | |||
| 19 | /* Reduce error messages. */ | 19 | /* Reduce error messages. */ |
| 20 | static pid_t tomoyo_last_pid; | 20 | static pid_t tomoyo_last_pid; |
| 21 | const pid_t pid = current->pid; | 21 | const pid_t pid = current->pid; |
| 22 | |||
| 22 | if (tomoyo_last_pid != pid) { | 23 | if (tomoyo_last_pid != pid) { |
| 23 | printk(KERN_WARNING "ERROR: Out of memory at %s.\n", | 24 | pr_warn("ERROR: Out of memory at %s.\n", function); |
| 24 | function); | ||
| 25 | tomoyo_last_pid = pid; | 25 | tomoyo_last_pid = pid; |
| 26 | } | 26 | } |
| 27 | if (!tomoyo_policy_loaded) | 27 | if (!tomoyo_policy_loaded) |
| @@ -48,6 +48,7 @@ bool tomoyo_memory_ok(void *ptr) | |||
| 48 | { | 48 | { |
| 49 | if (ptr) { | 49 | if (ptr) { |
| 50 | const size_t s = ksize(ptr); | 50 | const size_t s = ksize(ptr); |
| 51 | |||
| 51 | tomoyo_memory_used[TOMOYO_MEMORY_POLICY] += s; | 52 | tomoyo_memory_used[TOMOYO_MEMORY_POLICY] += s; |
| 52 | if (!tomoyo_memory_quota[TOMOYO_MEMORY_POLICY] || | 53 | if (!tomoyo_memory_quota[TOMOYO_MEMORY_POLICY] || |
| 53 | tomoyo_memory_used[TOMOYO_MEMORY_POLICY] <= | 54 | tomoyo_memory_used[TOMOYO_MEMORY_POLICY] <= |
| @@ -73,6 +74,7 @@ bool tomoyo_memory_ok(void *ptr) | |||
| 73 | void *tomoyo_commit_ok(void *data, const unsigned int size) | 74 | void *tomoyo_commit_ok(void *data, const unsigned int size) |
| 74 | { | 75 | { |
| 75 | void *ptr = kzalloc(size, GFP_NOFS); | 76 | void *ptr = kzalloc(size, GFP_NOFS); |
| 77 | |||
| 76 | if (tomoyo_memory_ok(ptr)) { | 78 | if (tomoyo_memory_ok(ptr)) { |
| 77 | memmove(ptr, data, size); | 79 | memmove(ptr, data, size); |
| 78 | memset(data, 0, size); | 80 | memset(data, 0, size); |
| @@ -98,6 +100,7 @@ struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param, | |||
| 98 | struct list_head *list; | 100 | struct list_head *list; |
| 99 | const char *group_name = tomoyo_read_token(param); | 101 | const char *group_name = tomoyo_read_token(param); |
| 100 | bool found = false; | 102 | bool found = false; |
| 103 | |||
| 101 | if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP) | 104 | if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP) |
| 102 | return NULL; | 105 | return NULL; |
| 103 | e.group_name = tomoyo_get_name(group_name); | 106 | e.group_name = tomoyo_get_name(group_name); |
| @@ -116,6 +119,7 @@ struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param, | |||
| 116 | } | 119 | } |
| 117 | if (!found) { | 120 | if (!found) { |
| 118 | struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e)); | 121 | struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e)); |
| 122 | |||
| 119 | if (entry) { | 123 | if (entry) { |
| 120 | INIT_LIST_HEAD(&entry->member_list); | 124 | INIT_LIST_HEAD(&entry->member_list); |
| 121 | atomic_set(&entry->head.users, 1); | 125 | atomic_set(&entry->head.users, 1); |
| @@ -191,6 +195,7 @@ struct tomoyo_policy_namespace tomoyo_kernel_namespace; | |||
| 191 | void __init tomoyo_mm_init(void) | 195 | void __init tomoyo_mm_init(void) |
| 192 | { | 196 | { |
| 193 | int idx; | 197 | int idx; |
| 198 | |||
| 194 | for (idx = 0; idx < TOMOYO_MAX_HASH; idx++) | 199 | for (idx = 0; idx < TOMOYO_MAX_HASH; idx++) |
| 195 | INIT_LIST_HEAD(&tomoyo_name_list[idx]); | 200 | INIT_LIST_HEAD(&tomoyo_name_list[idx]); |
| 196 | tomoyo_kernel_namespace.name = "<kernel>"; | 201 | tomoyo_kernel_namespace.name = "<kernel>"; |
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 7dc7f59b7dde..2755971f50df 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c | |||
| @@ -49,6 +49,7 @@ static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r, | |||
| 49 | { | 49 | { |
| 50 | const struct tomoyo_mount_acl *acl = | 50 | const struct tomoyo_mount_acl *acl = |
| 51 | container_of(ptr, typeof(*acl), head); | 51 | container_of(ptr, typeof(*acl), head); |
| 52 | |||
| 52 | return tomoyo_compare_number_union(r->param.mount.flags, | 53 | return tomoyo_compare_number_union(r->param.mount.flags, |
| 53 | &acl->flags) && | 54 | &acl->flags) && |
| 54 | tomoyo_compare_name_union(r->param.mount.type, | 55 | tomoyo_compare_name_union(r->param.mount.type, |
| @@ -89,6 +90,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, | |||
| 89 | struct tomoyo_path_info rdir; | 90 | struct tomoyo_path_info rdir; |
| 90 | int need_dev = 0; | 91 | int need_dev = 0; |
| 91 | int error = -ENOMEM; | 92 | int error = -ENOMEM; |
| 93 | |||
| 92 | r->obj = &obj; | 94 | r->obj = &obj; |
| 93 | 95 | ||
| 94 | /* Get fstype. */ | 96 | /* Get fstype. */ |
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 6ff8c21e4fff..85e6e31dd1e5 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c | |||
| @@ -94,11 +94,13 @@ static char *tomoyo_get_absolute_path(const struct path *path, char * const buff | |||
| 94 | const int buflen) | 94 | const int buflen) |
| 95 | { | 95 | { |
| 96 | char *pos = ERR_PTR(-ENOMEM); | 96 | char *pos = ERR_PTR(-ENOMEM); |
| 97 | |||
| 97 | if (buflen >= 256) { | 98 | if (buflen >= 256) { |
| 98 | /* go to whatever namespace root we are under */ | 99 | /* go to whatever namespace root we are under */ |
| 99 | pos = d_absolute_path(path, buffer, buflen - 1); | 100 | pos = d_absolute_path(path, buffer, buflen - 1); |
| 100 | if (!IS_ERR(pos) && *pos == '/' && pos[1]) { | 101 | if (!IS_ERR(pos) && *pos == '/' && pos[1]) { |
| 101 | struct inode *inode = d_backing_inode(path->dentry); | 102 | struct inode *inode = d_backing_inode(path->dentry); |
| 103 | |||
| 102 | if (inode && S_ISDIR(inode->i_mode)) { | 104 | if (inode && S_ISDIR(inode->i_mode)) { |
| 103 | buffer[buflen - 2] = '/'; | 105 | buffer[buflen - 2] = '/'; |
| 104 | buffer[buflen - 1] = '\0'; | 106 | buffer[buflen - 1] = '\0'; |
| @@ -123,10 +125,12 @@ static char *tomoyo_get_dentry_path(struct dentry *dentry, char * const buffer, | |||
| 123 | const int buflen) | 125 | const int buflen) |
| 124 | { | 126 | { |
| 125 | char *pos = ERR_PTR(-ENOMEM); | 127 | char *pos = ERR_PTR(-ENOMEM); |
| 128 | |||
| 126 | if (buflen >= 256) { | 129 | if (buflen >= 256) { |
| 127 | pos = dentry_path_raw(dentry, buffer, buflen - 1); | 130 | pos = dentry_path_raw(dentry, buffer, buflen - 1); |
| 128 | if (!IS_ERR(pos) && *pos == '/' && pos[1]) { | 131 | if (!IS_ERR(pos) && *pos == '/' && pos[1]) { |
| 129 | struct inode *inode = d_backing_inode(dentry); | 132 | struct inode *inode = d_backing_inode(dentry); |
| 133 | |||
| 130 | if (inode && S_ISDIR(inode->i_mode)) { | 134 | if (inode && S_ISDIR(inode->i_mode)) { |
| 131 | buffer[buflen - 2] = '/'; | 135 | buffer[buflen - 2] = '/'; |
| 132 | buffer[buflen - 1] = '\0'; | 136 | buffer[buflen - 1] = '\0'; |
| @@ -150,12 +154,14 @@ static char *tomoyo_get_local_path(struct dentry *dentry, char * const buffer, | |||
| 150 | { | 154 | { |
| 151 | struct super_block *sb = dentry->d_sb; | 155 | struct super_block *sb = dentry->d_sb; |
| 152 | char *pos = tomoyo_get_dentry_path(dentry, buffer, buflen); | 156 | char *pos = tomoyo_get_dentry_path(dentry, buffer, buflen); |
| 157 | |||
| 153 | if (IS_ERR(pos)) | 158 | if (IS_ERR(pos)) |
| 154 | return pos; | 159 | return pos; |
| 155 | /* Convert from $PID to self if $PID is current thread. */ | 160 | /* Convert from $PID to self if $PID is current thread. */ |
| 156 | if (sb->s_magic == PROC_SUPER_MAGIC && *pos == '/') { | 161 | if (sb->s_magic == PROC_SUPER_MAGIC && *pos == '/') { |
| 157 | char *ep; | 162 | char *ep; |
| 158 | const pid_t pid = (pid_t) simple_strtoul(pos + 1, &ep, 10); | 163 | const pid_t pid = (pid_t) simple_strtoul(pos + 1, &ep, 10); |
| 164 | |||
| 159 | if (*ep == '/' && pid && pid == | 165 | if (*ep == '/' && pid && pid == |
| 160 | task_tgid_nr_ns(current, sb->s_fs_info)) { | 166 | task_tgid_nr_ns(current, sb->s_fs_info)) { |
| 161 | pos = ep - 5; | 167 | pos = ep - 5; |
| @@ -170,6 +176,7 @@ static char *tomoyo_get_local_path(struct dentry *dentry, char * const buffer, | |||
| 170 | goto prepend_filesystem_name; | 176 | goto prepend_filesystem_name; |
| 171 | { | 177 | { |
| 172 | struct inode *inode = d_backing_inode(sb->s_root); | 178 | struct inode *inode = d_backing_inode(sb->s_root); |
| 179 | |||
| 173 | /* | 180 | /* |
| 174 | * Use filesystem name if filesystem does not support rename() | 181 | * Use filesystem name if filesystem does not support rename() |
| 175 | * operation. | 182 | * operation. |
| @@ -182,6 +189,7 @@ static char *tomoyo_get_local_path(struct dentry *dentry, char * const buffer, | |||
| 182 | char name[64]; | 189 | char name[64]; |
| 183 | int name_len; | 190 | int name_len; |
| 184 | const dev_t dev = sb->s_dev; | 191 | const dev_t dev = sb->s_dev; |
| 192 | |||
| 185 | name[sizeof(name) - 1] = '\0'; | 193 | name[sizeof(name) - 1] = '\0'; |
| 186 | snprintf(name, sizeof(name) - 1, "dev(%u,%u):", MAJOR(dev), | 194 | snprintf(name, sizeof(name) - 1, "dev(%u,%u):", MAJOR(dev), |
| 187 | MINOR(dev)); | 195 | MINOR(dev)); |
| @@ -197,6 +205,7 @@ prepend_filesystem_name: | |||
| 197 | { | 205 | { |
| 198 | const char *name = sb->s_type->name; | 206 | const char *name = sb->s_type->name; |
| 199 | const int name_len = strlen(name); | 207 | const int name_len = strlen(name); |
| 208 | |||
| 200 | pos -= name_len + 1; | 209 | pos -= name_len + 1; |
| 201 | if (pos < buffer) | 210 | if (pos < buffer) |
| 202 | goto out; | 211 | goto out; |
| @@ -223,10 +232,10 @@ static char *tomoyo_get_socket_name(const struct path *path, char * const buffer | |||
| 223 | struct inode *inode = d_backing_inode(path->dentry); | 232 | struct inode *inode = d_backing_inode(path->dentry); |
| 224 | struct socket *sock = inode ? SOCKET_I(inode) : NULL; | 233 | struct socket *sock = inode ? SOCKET_I(inode) : NULL; |
| 225 | struct sock *sk = sock ? sock->sk : NULL; | 234 | struct sock *sk = sock ? sock->sk : NULL; |
| 235 | |||
| 226 | if (sk) { | 236 | if (sk) { |
| 227 | snprintf(buffer, buflen, "socket:[family=%u:type=%u:" | 237 | snprintf(buffer, buflen, "socket:[family=%u:type=%u:protocol=%u]", |
| 228 | "protocol=%u]", sk->sk_family, sk->sk_type, | 238 | sk->sk_family, sk->sk_type, sk->sk_protocol); |
| 229 | sk->sk_protocol); | ||
| 230 | } else { | 239 | } else { |
| 231 | snprintf(buffer, buflen, "socket:[unknown]"); | 240 | snprintf(buffer, buflen, "socket:[unknown]"); |
| 232 | } | 241 | } |
| @@ -255,12 +264,14 @@ char *tomoyo_realpath_from_path(const struct path *path) | |||
| 255 | unsigned int buf_len = PAGE_SIZE / 2; | 264 | unsigned int buf_len = PAGE_SIZE / 2; |
| 256 | struct dentry *dentry = path->dentry; | 265 | struct dentry *dentry = path->dentry; |
| 257 | struct super_block *sb; | 266 | struct super_block *sb; |
| 267 | |||
| 258 | if (!dentry) | 268 | if (!dentry) |
| 259 | return NULL; | 269 | return NULL; |
| 260 | sb = dentry->d_sb; | 270 | sb = dentry->d_sb; |
| 261 | while (1) { | 271 | while (1) { |
| 262 | char *pos; | 272 | char *pos; |
| 263 | struct inode *inode; | 273 | struct inode *inode; |
| 274 | |||
| 264 | buf_len <<= 1; | 275 | buf_len <<= 1; |
| 265 | kfree(buf); | 276 | kfree(buf); |
| 266 | buf = kmalloc(buf_len, GFP_NOFS); | 277 | buf = kmalloc(buf_len, GFP_NOFS); |
| @@ -323,6 +334,7 @@ char *tomoyo_realpath_nofollow(const char *pathname) | |||
| 323 | 334 | ||
| 324 | if (pathname && kern_path(pathname, 0, &path) == 0) { | 335 | if (pathname && kern_path(pathname, 0, &path) == 0) { |
| 325 | char *buf = tomoyo_realpath_from_path(&path); | 336 | char *buf = tomoyo_realpath_from_path(&path); |
| 337 | |||
| 326 | path_put(&path); | 338 | path_put(&path); |
| 327 | return buf; | 339 | return buf; |
| 328 | } | 340 | } |
diff --git a/security/tomoyo/securityfs_if.c b/security/tomoyo/securityfs_if.c index 1d3d7e7a1f05..546281c5b233 100644 --- a/security/tomoyo/securityfs_if.c +++ b/security/tomoyo/securityfs_if.c | |||
| @@ -21,6 +21,7 @@ static bool tomoyo_check_task_acl(struct tomoyo_request_info *r, | |||
| 21 | { | 21 | { |
| 22 | const struct tomoyo_task_acl *acl = container_of(ptr, typeof(*acl), | 22 | const struct tomoyo_task_acl *acl = container_of(ptr, typeof(*acl), |
| 23 | head); | 23 | head); |
| 24 | |||
| 24 | return !tomoyo_pathcmp(r->param.task.domainname, acl->domainname); | 25 | return !tomoyo_pathcmp(r->param.task.domainname, acl->domainname); |
| 25 | } | 26 | } |
| 26 | 27 | ||
| @@ -42,6 +43,7 @@ static ssize_t tomoyo_write_self(struct file *file, const char __user *buf, | |||
| 42 | { | 43 | { |
| 43 | char *data; | 44 | char *data; |
| 44 | int error; | 45 | int error; |
| 46 | |||
| 45 | if (!count || count >= TOMOYO_EXEC_TMPSIZE - 10) | 47 | if (!count || count >= TOMOYO_EXEC_TMPSIZE - 10) |
| 46 | return -ENOMEM; | 48 | return -ENOMEM; |
| 47 | data = memdup_user_nul(buf, count); | 49 | data = memdup_user_nul(buf, count); |
| @@ -52,6 +54,7 @@ static ssize_t tomoyo_write_self(struct file *file, const char __user *buf, | |||
| 52 | const int idx = tomoyo_read_lock(); | 54 | const int idx = tomoyo_read_lock(); |
| 53 | struct tomoyo_path_info name; | 55 | struct tomoyo_path_info name; |
| 54 | struct tomoyo_request_info r; | 56 | struct tomoyo_request_info r; |
| 57 | |||
| 55 | name.name = data; | 58 | name.name = data; |
| 56 | tomoyo_fill_path_info(&name); | 59 | tomoyo_fill_path_info(&name); |
| 57 | /* Check "task manual_domain_transition" permission. */ | 60 | /* Check "task manual_domain_transition" permission. */ |
| @@ -67,18 +70,14 @@ static ssize_t tomoyo_write_self(struct file *file, const char __user *buf, | |||
| 67 | if (!new_domain) { | 70 | if (!new_domain) { |
| 68 | error = -ENOENT; | 71 | error = -ENOENT; |
| 69 | } else { | 72 | } else { |
| 70 | struct cred *cred = prepare_creds(); | 73 | struct tomoyo_task *s = tomoyo_task(current); |
| 71 | if (!cred) { | 74 | struct tomoyo_domain_info *old_domain = |
| 72 | error = -ENOMEM; | 75 | s->domain_info; |
| 73 | } else { | 76 | |
| 74 | struct tomoyo_domain_info *old_domain = | 77 | s->domain_info = new_domain; |
| 75 | cred->security; | 78 | atomic_inc(&new_domain->users); |
| 76 | cred->security = new_domain; | 79 | atomic_dec(&old_domain->users); |
| 77 | atomic_inc(&new_domain->users); | 80 | error = 0; |
| 78 | atomic_dec(&old_domain->users); | ||
| 79 | commit_creds(cred); | ||
| 80 | error = 0; | ||
| 81 | } | ||
| 82 | } | 81 | } |
| 83 | } | 82 | } |
| 84 | tomoyo_read_unlock(idx); | 83 | tomoyo_read_unlock(idx); |
| @@ -104,6 +103,7 @@ static ssize_t tomoyo_read_self(struct file *file, char __user *buf, | |||
| 104 | const char *domain = tomoyo_domain()->domainname->name; | 103 | const char *domain = tomoyo_domain()->domainname->name; |
| 105 | loff_t len = strlen(domain); | 104 | loff_t len = strlen(domain); |
| 106 | loff_t pos = *ppos; | 105 | loff_t pos = *ppos; |
| 106 | |||
| 107 | if (pos >= len || !count) | 107 | if (pos >= len || !count) |
| 108 | return 0; | 108 | return 0; |
| 109 | len -= pos; | 109 | len -= pos; |
| @@ -234,10 +234,14 @@ static void __init tomoyo_create_entry(const char *name, const umode_t mode, | |||
| 234 | */ | 234 | */ |
| 235 | static int __init tomoyo_initerface_init(void) | 235 | static int __init tomoyo_initerface_init(void) |
| 236 | { | 236 | { |
| 237 | struct tomoyo_domain_info *domain; | ||
| 237 | struct dentry *tomoyo_dir; | 238 | struct dentry *tomoyo_dir; |
| 238 | 239 | ||
| 240 | if (!tomoyo_enabled) | ||
| 241 | return 0; | ||
| 242 | domain = tomoyo_domain(); | ||
| 239 | /* Don't create securityfs entries unless registered. */ | 243 | /* Don't create securityfs entries unless registered. */ |
| 240 | if (current_cred()->security != &tomoyo_kernel_domain) | 244 | if (domain != &tomoyo_kernel_domain) |
| 241 | return 0; | 245 | return 0; |
| 242 | 246 | ||
| 243 | tomoyo_dir = securityfs_create_dir("tomoyo", NULL); | 247 | tomoyo_dir = securityfs_create_dir("tomoyo", NULL); |
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 1b5b5097efd7..716c92ec941a 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c | |||
| @@ -9,17 +9,19 @@ | |||
| 9 | #include "common.h" | 9 | #include "common.h" |
| 10 | 10 | ||
| 11 | /** | 11 | /** |
| 12 | * tomoyo_cred_alloc_blank - Target for security_cred_alloc_blank(). | 12 | * tomoyo_domain - Get "struct tomoyo_domain_info" for current thread. |
| 13 | * | 13 | * |
| 14 | * @new: Pointer to "struct cred". | 14 | * Returns pointer to "struct tomoyo_domain_info" for current thread. |
| 15 | * @gfp: Memory allocation flags. | ||
| 16 | * | ||
| 17 | * Returns 0. | ||
| 18 | */ | 15 | */ |
| 19 | static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) | 16 | struct tomoyo_domain_info *tomoyo_domain(void) |
| 20 | { | 17 | { |
| 21 | new->security = NULL; | 18 | struct tomoyo_task *s = tomoyo_task(current); |
| 22 | return 0; | 19 | |
| 20 | if (s->old_domain_info && !current->in_execve) { | ||
| 21 | atomic_dec(&s->old_domain_info->users); | ||
| 22 | s->old_domain_info = NULL; | ||
| 23 | } | ||
| 24 | return s->domain_info; | ||
| 23 | } | 25 | } |
| 24 | 26 | ||
| 25 | /** | 27 | /** |
| @@ -34,42 +36,38 @@ static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) | |||
| 34 | static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, | 36 | static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, |
| 35 | gfp_t gfp) | 37 | gfp_t gfp) |
| 36 | { | 38 | { |
| 37 | struct tomoyo_domain_info *domain = old->security; | 39 | /* Restore old_domain_info saved by previous execve() request. */ |
| 38 | new->security = domain; | 40 | struct tomoyo_task *s = tomoyo_task(current); |
| 39 | if (domain) | 41 | |
| 40 | atomic_inc(&domain->users); | 42 | if (s->old_domain_info && !current->in_execve) { |
| 43 | atomic_dec(&s->domain_info->users); | ||
| 44 | s->domain_info = s->old_domain_info; | ||
| 45 | s->old_domain_info = NULL; | ||
| 46 | } | ||
| 41 | return 0; | 47 | return 0; |
| 42 | } | 48 | } |
| 43 | 49 | ||
| 44 | /** | 50 | /** |
| 45 | * tomoyo_cred_transfer - Target for security_transfer_creds(). | 51 | * tomoyo_bprm_committed_creds - Target for security_bprm_committed_creds(). |
| 46 | * | 52 | * |
| 47 | * @new: Pointer to "struct cred". | 53 | * @bprm: Pointer to "struct linux_binprm". |
| 48 | * @old: Pointer to "struct cred". | ||
| 49 | */ | 54 | */ |
| 50 | static void tomoyo_cred_transfer(struct cred *new, const struct cred *old) | 55 | static void tomoyo_bprm_committed_creds(struct linux_binprm *bprm) |
| 51 | { | 56 | { |
| 52 | tomoyo_cred_prepare(new, old, 0); | 57 | /* Clear old_domain_info saved by execve() request. */ |
| 53 | } | 58 | struct tomoyo_task *s = tomoyo_task(current); |
| 54 | 59 | ||
| 55 | /** | 60 | atomic_dec(&s->old_domain_info->users); |
| 56 | * tomoyo_cred_free - Target for security_cred_free(). | 61 | s->old_domain_info = NULL; |
| 57 | * | ||
| 58 | * @cred: Pointer to "struct cred". | ||
| 59 | */ | ||
| 60 | static void tomoyo_cred_free(struct cred *cred) | ||
| 61 | { | ||
| 62 | struct tomoyo_domain_info *domain = cred->security; | ||
| 63 | if (domain) | ||
| 64 | atomic_dec(&domain->users); | ||
| 65 | } | 62 | } |
| 66 | 63 | ||
| 64 | #ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER | ||
| 67 | /** | 65 | /** |
| 68 | * tomoyo_bprm_set_creds - Target for security_bprm_set_creds(). | 66 | * tomoyo_bprm_set_creds - Target for security_bprm_set_creds(). |
| 69 | * | 67 | * |
| 70 | * @bprm: Pointer to "struct linux_binprm". | 68 | * @bprm: Pointer to "struct linux_binprm". |
| 71 | * | 69 | * |
| 72 | * Returns 0 on success, negative value otherwise. | 70 | * Returns 0. |
| 73 | */ | 71 | */ |
| 74 | static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) | 72 | static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) |
| 75 | { | 73 | { |
| @@ -79,29 +77,15 @@ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) | |||
| 79 | */ | 77 | */ |
| 80 | if (bprm->called_set_creds) | 78 | if (bprm->called_set_creds) |
| 81 | return 0; | 79 | return 0; |
| 82 | #ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER | ||
| 83 | /* | 80 | /* |
| 84 | * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested | 81 | * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested |
| 85 | * for the first time. | 82 | * for the first time. |
| 86 | */ | 83 | */ |
| 87 | if (!tomoyo_policy_loaded) | 84 | if (!tomoyo_policy_loaded) |
| 88 | tomoyo_load_policy(bprm->filename); | 85 | tomoyo_load_policy(bprm->filename); |
| 89 | #endif | ||
| 90 | /* | ||
| 91 | * Release reference to "struct tomoyo_domain_info" stored inside | ||
| 92 | * "bprm->cred->security". New reference to "struct tomoyo_domain_info" | ||
| 93 | * stored inside "bprm->cred->security" will be acquired later inside | ||
| 94 | * tomoyo_find_next_domain(). | ||
| 95 | */ | ||
| 96 | atomic_dec(&((struct tomoyo_domain_info *) | ||
| 97 | bprm->cred->security)->users); | ||
| 98 | /* | ||
| 99 | * Tell tomoyo_bprm_check_security() is called for the first time of an | ||
| 100 | * execve operation. | ||
| 101 | */ | ||
| 102 | bprm->cred->security = NULL; | ||
| 103 | return 0; | 86 | return 0; |
| 104 | } | 87 | } |
| 88 | #endif | ||
| 105 | 89 | ||
| 106 | /** | 90 | /** |
| 107 | * tomoyo_bprm_check_security - Target for security_bprm_check(). | 91 | * tomoyo_bprm_check_security - Target for security_bprm_check(). |
| @@ -112,23 +96,24 @@ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) | |||
| 112 | */ | 96 | */ |
| 113 | static int tomoyo_bprm_check_security(struct linux_binprm *bprm) | 97 | static int tomoyo_bprm_check_security(struct linux_binprm *bprm) |
| 114 | { | 98 | { |
| 115 | struct tomoyo_domain_info *domain = bprm->cred->security; | 99 | struct tomoyo_task *s = tomoyo_task(current); |
| 116 | 100 | ||
| 117 | /* | 101 | /* |
| 118 | * Execute permission is checked against pathname passed to do_execve() | 102 | * Execute permission is checked against pathname passed to do_execve() |
| 119 | * using current domain. | 103 | * using current domain. |
| 120 | */ | 104 | */ |
| 121 | if (!domain) { | 105 | if (!s->old_domain_info) { |
| 122 | const int idx = tomoyo_read_lock(); | 106 | const int idx = tomoyo_read_lock(); |
| 123 | const int err = tomoyo_find_next_domain(bprm); | 107 | const int err = tomoyo_find_next_domain(bprm); |
| 108 | |||
| 124 | tomoyo_read_unlock(idx); | 109 | tomoyo_read_unlock(idx); |
| 125 | return err; | 110 | return err; |
| 126 | } | 111 | } |
| 127 | /* | 112 | /* |
| 128 | * Read permission is checked against interpreters using next domain. | 113 | * Read permission is checked against interpreters using next domain. |
| 129 | */ | 114 | */ |
| 130 | return tomoyo_check_open_permission(domain, &bprm->file->f_path, | 115 | return tomoyo_check_open_permission(s->domain_info, |
| 131 | O_RDONLY); | 116 | &bprm->file->f_path, O_RDONLY); |
| 132 | } | 117 | } |
| 133 | 118 | ||
| 134 | /** | 119 | /** |
| @@ -167,6 +152,7 @@ static int tomoyo_path_truncate(const struct path *path) | |||
| 167 | static int tomoyo_path_unlink(const struct path *parent, struct dentry *dentry) | 152 | static int tomoyo_path_unlink(const struct path *parent, struct dentry *dentry) |
| 168 | { | 153 | { |
| 169 | struct path path = { .mnt = parent->mnt, .dentry = dentry }; | 154 | struct path path = { .mnt = parent->mnt, .dentry = dentry }; |
| 155 | |||
| 170 | return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path, NULL); | 156 | return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path, NULL); |
| 171 | } | 157 | } |
| 172 | 158 | ||
| @@ -183,6 +169,7 @@ static int tomoyo_path_mkdir(const struct path *parent, struct dentry *dentry, | |||
| 183 | umode_t mode) | 169 | umode_t mode) |
| 184 | { | 170 | { |
| 185 | struct path path = { .mnt = parent->mnt, .dentry = dentry }; | 171 | struct path path = { .mnt = parent->mnt, .dentry = dentry }; |
| 172 | |||
| 186 | return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path, | 173 | return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path, |
| 187 | mode & S_IALLUGO); | 174 | mode & S_IALLUGO); |
| 188 | } | 175 | } |
| @@ -198,6 +185,7 @@ static int tomoyo_path_mkdir(const struct path *parent, struct dentry *dentry, | |||
| 198 | static int tomoyo_path_rmdir(const struct path *parent, struct dentry *dentry) | 185 | static int tomoyo_path_rmdir(const struct path *parent, struct dentry *dentry) |
| 199 | { | 186 | { |
| 200 | struct path path = { .mnt = parent->mnt, .dentry = dentry }; | 187 | struct path path = { .mnt = parent->mnt, .dentry = dentry }; |
| 188 | |||
| 201 | return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path, NULL); | 189 | return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path, NULL); |
| 202 | } | 190 | } |
| 203 | 191 | ||
| @@ -214,6 +202,7 @@ static int tomoyo_path_symlink(const struct path *parent, struct dentry *dentry, | |||
| 214 | const char *old_name) | 202 | const char *old_name) |
| 215 | { | 203 | { |
| 216 | struct path path = { .mnt = parent->mnt, .dentry = dentry }; | 204 | struct path path = { .mnt = parent->mnt, .dentry = dentry }; |
| 205 | |||
| 217 | return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path, old_name); | 206 | return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path, old_name); |
| 218 | } | 207 | } |
| 219 | 208 | ||
| @@ -271,6 +260,7 @@ static int tomoyo_path_link(struct dentry *old_dentry, const struct path *new_di | |||
| 271 | { | 260 | { |
| 272 | struct path path1 = { .mnt = new_dir->mnt, .dentry = old_dentry }; | 261 | struct path path1 = { .mnt = new_dir->mnt, .dentry = old_dentry }; |
| 273 | struct path path2 = { .mnt = new_dir->mnt, .dentry = new_dentry }; | 262 | struct path path2 = { .mnt = new_dir->mnt, .dentry = new_dentry }; |
| 263 | |||
| 274 | return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2); | 264 | return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2); |
| 275 | } | 265 | } |
| 276 | 266 | ||
| @@ -291,6 +281,7 @@ static int tomoyo_path_rename(const struct path *old_parent, | |||
| 291 | { | 281 | { |
| 292 | struct path path1 = { .mnt = old_parent->mnt, .dentry = old_dentry }; | 282 | struct path path1 = { .mnt = old_parent->mnt, .dentry = old_dentry }; |
| 293 | struct path path2 = { .mnt = new_parent->mnt, .dentry = new_dentry }; | 283 | struct path path2 = { .mnt = new_parent->mnt, .dentry = new_dentry }; |
| 284 | |||
| 294 | return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2); | 285 | return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2); |
| 295 | } | 286 | } |
| 296 | 287 | ||
| @@ -322,11 +313,11 @@ static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, | |||
| 322 | */ | 313 | */ |
| 323 | static int tomoyo_file_open(struct file *f) | 314 | static int tomoyo_file_open(struct file *f) |
| 324 | { | 315 | { |
| 325 | int flags = f->f_flags; | ||
| 326 | /* Don't check read permission here if called from do_execve(). */ | 316 | /* Don't check read permission here if called from do_execve(). */ |
| 327 | if (current->in_execve) | 317 | if (current->in_execve) |
| 328 | return 0; | 318 | return 0; |
| 329 | return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags); | 319 | return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, |
| 320 | f->f_flags); | ||
| 330 | } | 321 | } |
| 331 | 322 | ||
| 332 | /** | 323 | /** |
| @@ -370,6 +361,7 @@ static int tomoyo_path_chmod(const struct path *path, umode_t mode) | |||
| 370 | static int tomoyo_path_chown(const struct path *path, kuid_t uid, kgid_t gid) | 361 | static int tomoyo_path_chown(const struct path *path, kuid_t uid, kgid_t gid) |
| 371 | { | 362 | { |
| 372 | int error = 0; | 363 | int error = 0; |
| 364 | |||
| 373 | if (uid_valid(uid)) | 365 | if (uid_valid(uid)) |
| 374 | error = tomoyo_path_number_perm(TOMOYO_TYPE_CHOWN, path, | 366 | error = tomoyo_path_number_perm(TOMOYO_TYPE_CHOWN, path, |
| 375 | from_kuid(&init_user_ns, uid)); | 367 | from_kuid(&init_user_ns, uid)); |
| @@ -419,6 +411,7 @@ static int tomoyo_sb_mount(const char *dev_name, const struct path *path, | |||
| 419 | static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) | 411 | static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) |
| 420 | { | 412 | { |
| 421 | struct path path = { .mnt = mnt, .dentry = mnt->mnt_root }; | 413 | struct path path = { .mnt = mnt, .dentry = mnt->mnt_root }; |
| 414 | |||
| 422 | return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path, NULL); | 415 | return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path, NULL); |
| 423 | } | 416 | } |
| 424 | 417 | ||
| @@ -493,16 +486,61 @@ static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg, | |||
| 493 | return tomoyo_socket_sendmsg_permission(sock, msg, size); | 486 | return tomoyo_socket_sendmsg_permission(sock, msg, size); |
| 494 | } | 487 | } |
| 495 | 488 | ||
| 489 | struct lsm_blob_sizes tomoyo_blob_sizes __lsm_ro_after_init = { | ||
| 490 | .lbs_task = sizeof(struct tomoyo_task), | ||
| 491 | }; | ||
| 492 | |||
| 493 | /** | ||
| 494 | * tomoyo_task_alloc - Target for security_task_alloc(). | ||
| 495 | * | ||
| 496 | * @task: Pointer to "struct task_struct". | ||
| 497 | * @flags: clone() flags. | ||
| 498 | * | ||
| 499 | * Returns 0. | ||
| 500 | */ | ||
| 501 | static int tomoyo_task_alloc(struct task_struct *task, | ||
| 502 | unsigned long clone_flags) | ||
| 503 | { | ||
| 504 | struct tomoyo_task *old = tomoyo_task(current); | ||
| 505 | struct tomoyo_task *new = tomoyo_task(task); | ||
| 506 | |||
| 507 | new->domain_info = old->domain_info; | ||
| 508 | atomic_inc(&new->domain_info->users); | ||
| 509 | new->old_domain_info = NULL; | ||
| 510 | return 0; | ||
| 511 | } | ||
| 512 | |||
| 513 | /** | ||
| 514 | * tomoyo_task_free - Target for security_task_free(). | ||
| 515 | * | ||
| 516 | * @task: Pointer to "struct task_struct". | ||
| 517 | */ | ||
| 518 | static void tomoyo_task_free(struct task_struct *task) | ||
| 519 | { | ||
| 520 | struct tomoyo_task *s = tomoyo_task(task); | ||
| 521 | |||
| 522 | if (s->domain_info) { | ||
| 523 | atomic_dec(&s->domain_info->users); | ||
| 524 | s->domain_info = NULL; | ||
| 525 | } | ||
| 526 | if (s->old_domain_info) { | ||
| 527 | atomic_dec(&s->old_domain_info->users); | ||
| 528 | s->old_domain_info = NULL; | ||
| 529 | } | ||
| 530 | } | ||
| 531 | |||
| 496 | /* | 532 | /* |
| 497 | * tomoyo_security_ops is a "struct security_operations" which is used for | 533 | * tomoyo_security_ops is a "struct security_operations" which is used for |
| 498 | * registering TOMOYO. | 534 | * registering TOMOYO. |
| 499 | */ | 535 | */ |
| 500 | static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = { | 536 | static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = { |
| 501 | LSM_HOOK_INIT(cred_alloc_blank, tomoyo_cred_alloc_blank), | ||
| 502 | LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare), | 537 | LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare), |
| 503 | LSM_HOOK_INIT(cred_transfer, tomoyo_cred_transfer), | 538 | LSM_HOOK_INIT(bprm_committed_creds, tomoyo_bprm_committed_creds), |
| 504 | LSM_HOOK_INIT(cred_free, tomoyo_cred_free), | 539 | LSM_HOOK_INIT(task_alloc, tomoyo_task_alloc), |
| 540 | LSM_HOOK_INIT(task_free, tomoyo_task_free), | ||
| 541 | #ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER | ||
| 505 | LSM_HOOK_INIT(bprm_set_creds, tomoyo_bprm_set_creds), | 542 | LSM_HOOK_INIT(bprm_set_creds, tomoyo_bprm_set_creds), |
| 543 | #endif | ||
| 506 | LSM_HOOK_INIT(bprm_check_security, tomoyo_bprm_check_security), | 544 | LSM_HOOK_INIT(bprm_check_security, tomoyo_bprm_check_security), |
| 507 | LSM_HOOK_INIT(file_fcntl, tomoyo_file_fcntl), | 545 | LSM_HOOK_INIT(file_fcntl, tomoyo_file_fcntl), |
| 508 | LSM_HOOK_INIT(file_open, tomoyo_file_open), | 546 | LSM_HOOK_INIT(file_open, tomoyo_file_open), |
| @@ -531,6 +569,8 @@ static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = { | |||
| 531 | /* Lock for GC. */ | 569 | /* Lock for GC. */ |
| 532 | DEFINE_SRCU(tomoyo_ss); | 570 | DEFINE_SRCU(tomoyo_ss); |
| 533 | 571 | ||
| 572 | int tomoyo_enabled __lsm_ro_after_init = 1; | ||
| 573 | |||
| 534 | /** | 574 | /** |
| 535 | * tomoyo_init - Register TOMOYO Linux as a LSM module. | 575 | * tomoyo_init - Register TOMOYO Linux as a LSM module. |
| 536 | * | 576 | * |
| @@ -538,19 +578,23 @@ DEFINE_SRCU(tomoyo_ss); | |||
| 538 | */ | 578 | */ |
| 539 | static int __init tomoyo_init(void) | 579 | static int __init tomoyo_init(void) |
| 540 | { | 580 | { |
| 541 | struct cred *cred = (struct cred *) current_cred(); | 581 | struct tomoyo_task *s = tomoyo_task(current); |
| 542 | 582 | ||
| 543 | if (!security_module_enable("tomoyo")) | ||
| 544 | return 0; | ||
| 545 | /* register ourselves with the security framework */ | 583 | /* register ourselves with the security framework */ |
| 546 | security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo"); | 584 | security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo"); |
| 547 | printk(KERN_INFO "TOMOYO Linux initialized\n"); | 585 | pr_info("TOMOYO Linux initialized\n"); |
| 548 | cred->security = &tomoyo_kernel_domain; | 586 | s->domain_info = &tomoyo_kernel_domain; |
| 587 | atomic_inc(&tomoyo_kernel_domain.users); | ||
| 588 | s->old_domain_info = NULL; | ||
| 549 | tomoyo_mm_init(); | 589 | tomoyo_mm_init(); |
| 590 | |||
| 550 | return 0; | 591 | return 0; |
| 551 | } | 592 | } |
| 552 | 593 | ||
| 553 | DEFINE_LSM(tomoyo) = { | 594 | DEFINE_LSM(tomoyo) = { |
| 554 | .name = "tomoyo", | 595 | .name = "tomoyo", |
| 596 | .enabled = &tomoyo_enabled, | ||
| 597 | .flags = LSM_FLAG_LEGACY_MAJOR, | ||
| 598 | .blobs = &tomoyo_blob_sizes, | ||
| 555 | .init = tomoyo_init, | 599 | .init = tomoyo_init, |
| 556 | }; | 600 | }; |
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index badffc8271c8..0517cbdd7275 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c | |||
| @@ -91,6 +91,7 @@ const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX] = { | |||
| 91 | void tomoyo_convert_time(time64_t time64, struct tomoyo_time *stamp) | 91 | void tomoyo_convert_time(time64_t time64, struct tomoyo_time *stamp) |
| 92 | { | 92 | { |
| 93 | struct tm tm; | 93 | struct tm tm; |
| 94 | |||
| 94 | time64_to_tm(time64, 0, &tm); | 95 | time64_to_tm(time64, 0, &tm); |
| 95 | stamp->sec = tm.tm_sec; | 96 | stamp->sec = tm.tm_sec; |
| 96 | stamp->min = tm.tm_min; | 97 | stamp->min = tm.tm_min; |
| @@ -113,6 +114,7 @@ void tomoyo_convert_time(time64_t time64, struct tomoyo_time *stamp) | |||
| 113 | bool tomoyo_permstr(const char *string, const char *keyword) | 114 | bool tomoyo_permstr(const char *string, const char *keyword) |
| 114 | { | 115 | { |
| 115 | const char *cp = strstr(string, keyword); | 116 | const char *cp = strstr(string, keyword); |
| 117 | |||
| 116 | if (cp) | 118 | if (cp) |
| 117 | return cp == string || *(cp - 1) == '/'; | 119 | return cp == string || *(cp - 1) == '/'; |
| 118 | return false; | 120 | return false; |
| @@ -132,6 +134,7 @@ char *tomoyo_read_token(struct tomoyo_acl_param *param) | |||
| 132 | { | 134 | { |
| 133 | char *pos = param->data; | 135 | char *pos = param->data; |
| 134 | char *del = strchr(pos, ' '); | 136 | char *del = strchr(pos, ' '); |
| 137 | |||
| 135 | if (del) | 138 | if (del) |
| 136 | *del++ = '\0'; | 139 | *del++ = '\0'; |
| 137 | else | 140 | else |
| @@ -152,6 +155,7 @@ const struct tomoyo_path_info *tomoyo_get_domainname | |||
| 152 | { | 155 | { |
| 153 | char *start = param->data; | 156 | char *start = param->data; |
| 154 | char *pos = start; | 157 | char *pos = start; |
| 158 | |||
| 155 | while (*pos) { | 159 | while (*pos) { |
| 156 | if (*pos++ != ' ' || *pos++ == '/') | 160 | if (*pos++ != ' ' || *pos++ == '/') |
| 157 | continue; | 161 | continue; |
| @@ -181,8 +185,10 @@ u8 tomoyo_parse_ulong(unsigned long *result, char **str) | |||
| 181 | const char *cp = *str; | 185 | const char *cp = *str; |
| 182 | char *ep; | 186 | char *ep; |
| 183 | int base = 10; | 187 | int base = 10; |
| 188 | |||
| 184 | if (*cp == '0') { | 189 | if (*cp == '0') { |
| 185 | char c = *(cp + 1); | 190 | char c = *(cp + 1); |
| 191 | |||
| 186 | if (c == 'x' || c == 'X') { | 192 | if (c == 'x' || c == 'X') { |
| 187 | base = 16; | 193 | base = 16; |
| 188 | cp += 2; | 194 | cp += 2; |
| @@ -240,6 +246,7 @@ bool tomoyo_parse_name_union(struct tomoyo_acl_param *param, | |||
| 240 | struct tomoyo_name_union *ptr) | 246 | struct tomoyo_name_union *ptr) |
| 241 | { | 247 | { |
| 242 | char *filename; | 248 | char *filename; |
| 249 | |||
| 243 | if (param->data[0] == '@') { | 250 | if (param->data[0] == '@') { |
| 244 | param->data++; | 251 | param->data++; |
| 245 | ptr->group = tomoyo_get_group(param, TOMOYO_PATH_GROUP); | 252 | ptr->group = tomoyo_get_group(param, TOMOYO_PATH_GROUP); |
| @@ -266,6 +273,7 @@ bool tomoyo_parse_number_union(struct tomoyo_acl_param *param, | |||
| 266 | char *data; | 273 | char *data; |
| 267 | u8 type; | 274 | u8 type; |
| 268 | unsigned long v; | 275 | unsigned long v; |
| 276 | |||
| 269 | memset(ptr, 0, sizeof(*ptr)); | 277 | memset(ptr, 0, sizeof(*ptr)); |
| 270 | if (param->data[0] == '@') { | 278 | if (param->data[0] == '@') { |
| 271 | param->data++; | 279 | param->data++; |
| @@ -429,6 +437,7 @@ static bool tomoyo_correct_word2(const char *string, size_t len) | |||
| 429 | unsigned char c; | 437 | unsigned char c; |
| 430 | unsigned char d; | 438 | unsigned char d; |
| 431 | unsigned char e; | 439 | unsigned char e; |
| 440 | |||
| 432 | if (!len) | 441 | if (!len) |
| 433 | goto out; | 442 | goto out; |
| 434 | while (len--) { | 443 | while (len--) { |
| @@ -533,6 +542,7 @@ bool tomoyo_correct_domain(const unsigned char *domainname) | |||
| 533 | return true; | 542 | return true; |
| 534 | while (1) { | 543 | while (1) { |
| 535 | const unsigned char *cp = strchr(domainname, ' '); | 544 | const unsigned char *cp = strchr(domainname, ' '); |
| 545 | |||
| 536 | if (!cp) | 546 | if (!cp) |
| 537 | break; | 547 | break; |
| 538 | if (*domainname != '/' || | 548 | if (*domainname != '/' || |
| @@ -554,6 +564,7 @@ bool tomoyo_domain_def(const unsigned char *buffer) | |||
| 554 | { | 564 | { |
| 555 | const unsigned char *cp; | 565 | const unsigned char *cp; |
| 556 | int len; | 566 | int len; |
| 567 | |||
| 557 | if (*buffer != '<') | 568 | if (*buffer != '<') |
| 558 | return false; | 569 | return false; |
| 559 | cp = strchr(buffer, ' '); | 570 | cp = strchr(buffer, ' '); |
| @@ -668,6 +679,9 @@ static bool tomoyo_file_matches_pattern2(const char *filename, | |||
| 668 | { | 679 | { |
| 669 | while (filename < filename_end && pattern < pattern_end) { | 680 | while (filename < filename_end && pattern < pattern_end) { |
| 670 | char c; | 681 | char c; |
| 682 | int i; | ||
| 683 | int j; | ||
| 684 | |||
| 671 | if (*pattern != '\\') { | 685 | if (*pattern != '\\') { |
| 672 | if (*filename++ != *pattern++) | 686 | if (*filename++ != *pattern++) |
| 673 | return false; | 687 | return false; |
| @@ -676,8 +690,6 @@ static bool tomoyo_file_matches_pattern2(const char *filename, | |||
| 676 | c = *filename; | 690 | c = *filename; |
| 677 | pattern++; | 691 | pattern++; |
| 678 | switch (*pattern) { | 692 | switch (*pattern) { |
| 679 | int i; | ||
| 680 | int j; | ||
| 681 | case '?': | 693 | case '?': |
| 682 | if (c == '/') { | 694 | if (c == '/') { |
| 683 | return false; | 695 | return false; |
| @@ -985,6 +997,7 @@ int tomoyo_init_request_info(struct tomoyo_request_info *r, | |||
| 985 | struct tomoyo_domain_info *domain, const u8 index) | 997 | struct tomoyo_domain_info *domain, const u8 index) |
| 986 | { | 998 | { |
| 987 | u8 profile; | 999 | u8 profile; |
| 1000 | |||
| 988 | memset(r, 0, sizeof(*r)); | 1001 | memset(r, 0, sizeof(*r)); |
| 989 | if (!domain) | 1002 | if (!domain) |
| 990 | domain = tomoyo_domain(); | 1003 | domain = tomoyo_domain(); |
| @@ -1018,6 +1031,7 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) | |||
| 1018 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 1031 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
| 1019 | u16 perm; | 1032 | u16 perm; |
| 1020 | u8 i; | 1033 | u8 i; |
| 1034 | |||
| 1021 | if (ptr->is_deleted) | 1035 | if (ptr->is_deleted) |
| 1022 | continue; | 1036 | continue; |
| 1023 | switch (ptr->type) { | 1037 | switch (ptr->type) { |
| @@ -1062,9 +1076,8 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) | |||
| 1062 | domain->flags[TOMOYO_DIF_QUOTA_WARNED] = true; | 1076 | domain->flags[TOMOYO_DIF_QUOTA_WARNED] = true; |
| 1063 | /* r->granted = false; */ | 1077 | /* r->granted = false; */ |
| 1064 | tomoyo_write_log(r, "%s", tomoyo_dif[TOMOYO_DIF_QUOTA_WARNED]); | 1078 | tomoyo_write_log(r, "%s", tomoyo_dif[TOMOYO_DIF_QUOTA_WARNED]); |
| 1065 | printk(KERN_WARNING "WARNING: " | 1079 | pr_warn("WARNING: Domain '%s' has too many ACLs to hold. Stopped learning mode.\n", |
| 1066 | "Domain '%s' has too many ACLs to hold. " | 1080 | domain->domainname->name); |
| 1067 | "Stopped learning mode.\n", domain->domainname->name); | ||
| 1068 | } | 1081 | } |
| 1069 | return false; | 1082 | return false; |
| 1070 | } | 1083 | } |
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index 02514fe558b4..57cc60722dd3 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c | |||
| @@ -479,9 +479,15 @@ static void __init yama_init_sysctl(void) | |||
| 479 | static inline void yama_init_sysctl(void) { } | 479 | static inline void yama_init_sysctl(void) { } |
| 480 | #endif /* CONFIG_SYSCTL */ | 480 | #endif /* CONFIG_SYSCTL */ |
| 481 | 481 | ||
| 482 | void __init yama_add_hooks(void) | 482 | static int __init yama_init(void) |
| 483 | { | 483 | { |
| 484 | pr_info("Yama: becoming mindful.\n"); | 484 | pr_info("Yama: becoming mindful.\n"); |
| 485 | security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), "yama"); | 485 | security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), "yama"); |
| 486 | yama_init_sysctl(); | 486 | yama_init_sysctl(); |
| 487 | return 0; | ||
| 487 | } | 488 | } |
| 489 | |||
| 490 | DEFINE_LSM(yama) = { | ||
| 491 | .name = "yama", | ||
| 492 | .init = yama_init, | ||
| 493 | }; | ||
