Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: (90 commits)
AppArmor: fix build warnings for non-const use of get_task_cred
selinux: convert the policy type_attr_map to flex_array
AppArmor: Enable configuring and building of the AppArmor security module
TOMOYO: Use pathname specified by policy rather than execve()
AppArmor: update path_truncate method to latest version
AppArmor: core policy routines
AppArmor: policy routines for loading and unpacking policy
AppArmor: mediation of non file objects
AppArmor: LSM interface, and security module initialization
AppArmor: Enable configuring and building of the AppArmor security module
AppArmor: update Maintainer and Documentation
AppArmor: functions for domain transitions
AppArmor: file enforcement routines
AppArmor: userspace interfaces
AppArmor: dfa match engine
AppArmor: contexts used in attaching policy to system objects
AppArmor: basic auditing infrastructure.
AppArmor: misc. base functions and defines
TOMOYO: Update version to 2.3.0
TOMOYO: Fix quota check.
...

+13405 -4713
+39
Documentation/apparmor.txt
··· 1 + --- What is AppArmor? --- 2 + 3 + AppArmor is MAC style security extension for the Linux kernel. It implements 4 + a task centered policy, with task "profiles" being created and loaded 5 + from user space. Tasks on the system that do not have a profile defined for 6 + them run in an unconfined state which is equivalent to standard Linux DAC 7 + permissions. 8 + 9 + --- How to enable/disable --- 10 + 11 + set CONFIG_SECURITY_APPARMOR=y 12 + 13 + If AppArmor should be selected as the default security module then 14 + set CONFIG_DEFAULT_SECURITY="apparmor" 15 + and CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1 16 + 17 + Build the kernel 18 + 19 + If AppArmor is not the default security module it can be enabled by passing 20 + security=apparmor on the kernel's command line. 21 + 22 + If AppArmor is the default security module it can be disabled by passing 23 + apparmor=0, security=XXXX (where XXX is valid security module), on the 24 + kernel's command line 25 + 26 + For AppArmor to enforce any restrictions beyond standard Linux DAC permissions 27 + policy must be loaded into the kernel from user space (see the Documentation 28 + and tools links). 29 + 30 + --- Documentation --- 31 + 32 + Documentation can be found on the wiki. 33 + 34 + --- Links --- 35 + 36 + Mailing List - apparmor@lists.ubuntu.com 37 + Wiki - http://apparmor.wiki.kernel.org/ 38 + User space tools - https://launchpad.net/apparmor 39 + Kernel module - git://git.kernel.org/pub/scm/linux/kernel/git/jj/apparmor-dev.git
+8
Documentation/kernel-parameters.txt
··· 93 93 Documentation/scsi/. 94 94 SECURITY Different security models are enabled. 95 95 SELINUX SELinux support is enabled. 96 + APPARMOR AppArmor support is enabled. 96 97 SERIAL Serial support is enabled. 97 98 SH SuperH architecture is enabled. 98 99 SMP The kernel is an SMP kernel. ··· 2312 2311 Default value is set via kernel config option. 2313 2312 If enabled at boot time, /selinux/disable can be used 2314 2313 later to disable prior to initial policy load. 2314 + 2315 + apparmor= [APPARMOR] Disable or enable AppArmor at boot time 2316 + Format: { "0" | "1" } 2317 + See security/apparmor/Kconfig help text 2318 + 0 -- disable. 2319 + 1 -- enable. 2320 + Default value is set via kernel config option. 2315 2321 2316 2322 serialnumber [BUGS=X86-32] 2317 2323
+5 -5
Documentation/tomoyo.txt
··· 3 3 TOMOYO is a name-based MAC extension (LSM module) for the Linux kernel. 4 4 5 5 LiveCD-based tutorials are available at 6 - http://tomoyo.sourceforge.jp/en/1.6.x/1st-step/ubuntu8.04-live/ 7 - http://tomoyo.sourceforge.jp/en/1.6.x/1st-step/centos5-live/ . 6 + http://tomoyo.sourceforge.jp/1.7/1st-step/ubuntu10.04-live/ 7 + http://tomoyo.sourceforge.jp/1.7/1st-step/centos5-live/ . 8 8 Though these tutorials use non-LSM version of TOMOYO, they are useful for you 9 9 to know what TOMOYO is. 10 10 ··· 13 13 Build the kernel with CONFIG_SECURITY_TOMOYO=y and pass "security=tomoyo" on 14 14 kernel's command line. 15 15 16 - Please see http://tomoyo.sourceforge.jp/en/2.2.x/ for details. 16 + Please see http://tomoyo.sourceforge.jp/2.3/ for details. 17 17 18 18 --- Where is documentation? --- 19 19 20 20 User <-> Kernel interface documentation is available at 21 - http://tomoyo.sourceforge.jp/en/2.2.x/policy-reference.html . 21 + http://tomoyo.sourceforge.jp/2.3/policy-reference.html . 22 22 23 23 Materials we prepared for seminars and symposiums are available at 24 24 http://sourceforge.jp/projects/tomoyo/docs/?category_id=532&language_id=1 . ··· 50 50 SELinux/SMACK/AppArmor etc. when you want to use TOMOYO. 51 51 52 52 We hope that LSM becomes stackable in future. Meanwhile, you can use non-LSM 53 - version of TOMOYO, available at http://tomoyo.sourceforge.jp/en/1.6.x/ . 53 + version of TOMOYO, available at http://tomoyo.sourceforge.jp/1.7/ . 54 54 LSM version of TOMOYO is a subset of non-LSM version of TOMOYO. We are planning 55 55 to port non-LSM version's functionalities to LSM versions.
+9 -1
MAINTAINERS
··· 5061 5061 F: include/linux/selinux* 5062 5062 F: security/selinux/ 5063 5063 5064 + APPARMOR SECURITY MODULE 5065 + M: John Johansen <john.johansen@canonical.com> 5066 + L: apparmor@lists.ubuntu.com (subscribers-only, general discussion) 5067 + W: apparmor.wiki.kernel.org 5068 + T: git git://git.kernel.org/pub/scm/linux/kernel/git/jj/apparmor-dev.git 5069 + S: Supported 5070 + F: security/apparmor/ 5071 + 5064 5072 SENSABLE PHANTOM 5065 5073 M: Jiri Slaby <jirislaby@gmail.com> 5066 5074 S: Maintained ··· 5613 5605 L: tomoyo-dev@lists.sourceforge.jp (subscribers-only, for developers in Japanese) 5614 5606 L: tomoyo-users@lists.sourceforge.jp (subscribers-only, for users in Japanese) 5615 5607 W: http://tomoyo.sourceforge.jp/ 5616 - T: quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.2.x/tomoyo-lsm/patches/ 5608 + T: quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.3.x/tomoyo-lsm/patches/ 5617 5609 S: Maintained 5618 5610 F: security/tomoyo/ 5619 5611
+1 -1
fs/fuse/dir.c
··· 1016 1016 exist. So if permissions are revoked this won't be 1017 1017 noticed immediately, only after the attribute 1018 1018 timeout has expired */ 1019 - } else if (mask & MAY_ACCESS) { 1019 + } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { 1020 1020 err = fuse_access(inode, mask); 1021 1021 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { 1022 1022 if (!(inode->i_mode & S_IXUGO)) {
+2 -4
fs/namei.c
··· 282 282 if (retval) 283 283 return retval; 284 284 285 - return security_inode_permission(inode, 286 - mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND)); 285 + return security_inode_permission(inode, mask); 287 286 } 288 287 289 288 /** ··· 1483 1484 */ 1484 1485 error = locks_verify_locked(inode); 1485 1486 if (!error) 1486 - error = security_path_truncate(path, 0, 1487 - ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); 1487 + error = security_path_truncate(path); 1488 1488 if (!error) { 1489 1489 error = do_truncate(path->dentry, 0, 1490 1490 ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
+1 -1
fs/nfs/dir.c
··· 1953 1953 if ((mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) 1954 1954 goto out; 1955 1955 /* Is this sys_access() ? */ 1956 - if (mask & MAY_ACCESS) 1956 + if (mask & (MAY_ACCESS | MAY_CHDIR)) 1957 1957 goto force_lookup; 1958 1958 1959 1959 switch (inode->i_mode & S_IFMT) {
+5 -6
fs/open.c
··· 110 110 111 111 error = locks_verify_truncate(inode, NULL, length); 112 112 if (!error) 113 - error = security_path_truncate(&path, length, 0); 113 + error = security_path_truncate(&path); 114 114 if (!error) 115 115 error = do_truncate(path.dentry, length, 0, NULL); 116 116 ··· 165 165 166 166 error = locks_verify_truncate(inode, file, length); 167 167 if (!error) 168 - error = security_path_truncate(&file->f_path, length, 169 - ATTR_MTIME|ATTR_CTIME); 168 + error = security_path_truncate(&file->f_path); 170 169 if (!error) 171 170 error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); 172 171 out_putf: ··· 366 367 if (error) 367 368 goto out; 368 369 369 - error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); 370 + error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR); 370 371 if (error) 371 372 goto dput_and_out; 372 373 ··· 395 396 if (!S_ISDIR(inode->i_mode)) 396 397 goto out_putf; 397 398 398 - error = inode_permission(inode, MAY_EXEC | MAY_ACCESS); 399 + error = inode_permission(inode, MAY_EXEC | MAY_CHDIR); 399 400 if (!error) 400 401 set_fs_pwd(current->fs, &file->f_path); 401 402 out_putf: ··· 413 414 if (error) 414 415 goto out; 415 416 416 - error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); 417 + error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR); 417 418 if (error) 418 419 goto dput_and_out; 419 420
-3
include/linux/capability.h
··· 49 49 } __user *cap_user_data_t; 50 50 51 51 52 - #define XATTR_CAPS_SUFFIX "capability" 53 - #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX 54 - 55 52 #define VFS_CAP_REVISION_MASK 0xFF000000 56 53 #define VFS_CAP_REVISION_SHIFT 24 57 54 #define VFS_CAP_FLAGS_MASK ~VFS_CAP_REVISION_MASK
+1
include/linux/fs.h
··· 53 53 #define MAY_APPEND 8 54 54 #define MAY_ACCESS 16 55 55 #define MAY_OPEN 32 56 + #define MAY_CHDIR 64 56 57 57 58 /* 58 59 * flags in file.f_mode. Note that FMODE_READ and FMODE_WRITE must correspond
+32
include/linux/lsm_audit.h
··· 90 90 u32 requested; 91 91 u32 audited; 92 92 u32 denied; 93 + /* 94 + * auditdeny is a bit tricky and unintuitive. See the 95 + * comments in avc.c for it's meaning and usage. 96 + */ 97 + u32 auditdeny; 93 98 struct av_decision *avd; 94 99 int result; 95 100 } selinux_audit_data; 101 + #endif 102 + #ifdef CONFIG_SECURITY_APPARMOR 103 + struct { 104 + int error; 105 + int op; 106 + int type; 107 + void *profile; 108 + const char *name; 109 + const char *info; 110 + union { 111 + void *target; 112 + struct { 113 + long pos; 114 + void *target; 115 + } iface; 116 + struct { 117 + int rlim; 118 + unsigned long max; 119 + } rlim; 120 + struct { 121 + const char *target; 122 + u32 request; 123 + u32 denied; 124 + uid_t ouid; 125 + } fs; 126 + }; 127 + } apparmor_audit_data; 96 128 #endif 97 129 }; 98 130 /* these callback will be implemented by a specific LSM */
+3 -8
include/linux/security.h
··· 470 470 * @path_truncate: 471 471 * Check permission before truncating a file. 472 472 * @path contains the path structure for the file. 473 - * @length is the new length of the file. 474 - * @time_attrs is the flags passed to do_truncate(). 475 473 * Return 0 if permission is granted. 476 474 * @inode_getattr: 477 475 * Check permission before obtaining file attributes. ··· 1410 1412 int (*path_rmdir) (struct path *dir, struct dentry *dentry); 1411 1413 int (*path_mknod) (struct path *dir, struct dentry *dentry, int mode, 1412 1414 unsigned int dev); 1413 - int (*path_truncate) (struct path *path, loff_t length, 1414 - unsigned int time_attrs); 1415 + int (*path_truncate) (struct path *path); 1415 1416 int (*path_symlink) (struct path *dir, struct dentry *dentry, 1416 1417 const char *old_name); 1417 1418 int (*path_link) (struct dentry *old_dentry, struct path *new_dir, ··· 2803 2806 int security_path_rmdir(struct path *dir, struct dentry *dentry); 2804 2807 int security_path_mknod(struct path *dir, struct dentry *dentry, int mode, 2805 2808 unsigned int dev); 2806 - int security_path_truncate(struct path *path, loff_t length, 2807 - unsigned int time_attrs); 2809 + int security_path_truncate(struct path *path); 2808 2810 int security_path_symlink(struct path *dir, struct dentry *dentry, 2809 2811 const char *old_name); 2810 2812 int security_path_link(struct dentry *old_dentry, struct path *new_dir, ··· 2837 2841 return 0; 2838 2842 } 2839 2843 2840 - static inline int security_path_truncate(struct path *path, loff_t length, 2841 - unsigned int time_attrs) 2844 + static inline int security_path_truncate(struct path *path) 2842 2845 { 2843 2846 return 0; 2844 2847 }
+14
include/linux/xattr.h
··· 33 33 #define XATTR_USER_PREFIX "user." 34 34 #define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1) 35 35 36 + /* Security namespace */ 37 + #define XATTR_SELINUX_SUFFIX "selinux" 38 + #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX 39 + 40 + #define XATTR_SMACK_SUFFIX "SMACK64" 41 + #define XATTR_SMACK_IPIN "SMACK64IPIN" 42 + #define XATTR_SMACK_IPOUT "SMACK64IPOUT" 43 + #define XATTR_NAME_SMACK XATTR_SECURITY_PREFIX XATTR_SMACK_SUFFIX 44 + #define XATTR_NAME_SMACKIPIN XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN 45 + #define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT 46 + 47 + #define XATTR_CAPS_SUFFIX "capability" 48 + #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX 49 + 36 50 struct inode; 37 51 struct dentry; 38 52
+6
security/Kconfig
··· 140 140 source security/selinux/Kconfig 141 141 source security/smack/Kconfig 142 142 source security/tomoyo/Kconfig 143 + source security/apparmor/Kconfig 143 144 144 145 source security/integrity/ima/Kconfig 145 146 ··· 149 148 default DEFAULT_SECURITY_SELINUX if SECURITY_SELINUX 150 149 default DEFAULT_SECURITY_SMACK if SECURITY_SMACK 151 150 default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO 151 + default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR 152 152 default DEFAULT_SECURITY_DAC 153 153 154 154 help ··· 165 163 config DEFAULT_SECURITY_TOMOYO 166 164 bool "TOMOYO" if SECURITY_TOMOYO=y 167 165 166 + config DEFAULT_SECURITY_APPARMOR 167 + bool "AppArmor" if SECURITY_APPARMOR=y 168 + 168 169 config DEFAULT_SECURITY_DAC 169 170 bool "Unix Discretionary Access Controls" 170 171 ··· 178 173 default "selinux" if DEFAULT_SECURITY_SELINUX 179 174 default "smack" if DEFAULT_SECURITY_SMACK 180 175 default "tomoyo" if DEFAULT_SECURITY_TOMOYO 176 + default "apparmor" if DEFAULT_SECURITY_APPARMOR 181 177 default "" if DEFAULT_SECURITY_DAC 182 178 183 179 endmenu
+2
security/Makefile
··· 6 6 subdir-$(CONFIG_SECURITY_SELINUX) += selinux 7 7 subdir-$(CONFIG_SECURITY_SMACK) += smack 8 8 subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo 9 + subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor 9 10 10 11 # always enable default capabilities 11 12 obj-y += commoncap.o ··· 20 19 obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o 21 20 obj-$(CONFIG_AUDIT) += lsm_audit.o 22 21 obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o 22 + obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/built-in.o 23 23 obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o 24 24 25 25 # Object integrity file lists
+5
security/apparmor/.gitignore
··· 1 + # 2 + # Generated include files 3 + # 4 + af_names.h 5 + capability_names.h
+31
security/apparmor/Kconfig
··· 1 + config SECURITY_APPARMOR 2 + bool "AppArmor support" 3 + depends on SECURITY 4 + select AUDIT 5 + select SECURITY_PATH 6 + select SECURITYFS 7 + select SECURITY_NETWORK 8 + default n 9 + help 10 + This enables the AppArmor security module. 11 + Required userspace tools (if they are not included in your 12 + distribution) and further information may be found at 13 + http://apparmor.wiki.kernel.org 14 + 15 + If you are unsure how to answer this question, answer N. 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.
+24
security/apparmor/Makefile
··· 1 + # Makefile for AppArmor Linux Security Module 2 + # 3 + obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o 4 + 5 + apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ 6 + path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ 7 + resource.o sid.o file.o 8 + 9 + clean-files: capability_names.h af_names.h 10 + 11 + quiet_cmd_make-caps = GEN $@ 12 + cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ; sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ 13 + 14 + quiet_cmd_make-rlim = GEN $@ 15 + cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ; sed -n --e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+RLIMIT_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ ; echo "static const int rlim_map[] = {" >> $@ ; sed -n -e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+\\(RLIMIT_[A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/\\1,/p" $< >> $@ ; echo "};" >> $@ 16 + 17 + $(obj)/capability.o : $(obj)/capability_names.h 18 + $(obj)/resource.o : $(obj)/rlim_names.h 19 + $(obj)/capability_names.h : $(srctree)/include/linux/capability.h 20 + $(call cmd,make-caps) 21 + $(obj)/af_names.h : $(srctree)/include/linux/socket.h 22 + $(call cmd,make-af) 23 + $(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h 24 + $(call cmd,make-rlim)
+239
security/apparmor/apparmorfs.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor /sys/kernel/security/apparmor interface functions 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #include <linux/security.h> 16 + #include <linux/vmalloc.h> 17 + #include <linux/module.h> 18 + #include <linux/seq_file.h> 19 + #include <linux/uaccess.h> 20 + #include <linux/namei.h> 21 + 22 + #include "include/apparmor.h" 23 + #include "include/apparmorfs.h" 24 + #include "include/audit.h" 25 + #include "include/context.h" 26 + #include "include/policy.h" 27 + 28 + /** 29 + * aa_simple_write_to_buffer - common routine for getting policy from user 30 + * @op: operation doing the user buffer copy 31 + * @userbuf: user buffer to copy data from (NOT NULL) 32 + * @alloc_size: size of user buffer 33 + * @copy_size: size of data to copy from user buffer 34 + * @pos: position write is at in the file (NOT NULL) 35 + * 36 + * Returns: kernel buffer containing copy of user buffer data or an 37 + * ERR_PTR on failure. 38 + */ 39 + static char *aa_simple_write_to_buffer(int op, const char __user *userbuf, 40 + size_t alloc_size, size_t copy_size, 41 + loff_t *pos) 42 + { 43 + char *data; 44 + 45 + if (*pos != 0) 46 + /* only writes from pos 0, that is complete writes */ 47 + return ERR_PTR(-ESPIPE); 48 + 49 + /* 50 + * Don't allow profile load/replace/remove from profiles that don't 51 + * have CAP_MAC_ADMIN 52 + */ 53 + if (!aa_may_manage_policy(op)) 54 + return ERR_PTR(-EACCES); 55 + 56 + /* freed by caller to simple_write_to_buffer */ 57 + data = kvmalloc(alloc_size); 58 + if (data == NULL) 59 + return ERR_PTR(-ENOMEM); 60 + 61 + if (copy_from_user(data, userbuf, copy_size)) { 62 + kvfree(data); 63 + return ERR_PTR(-EFAULT); 64 + } 65 + 66 + return data; 67 + } 68 + 69 + 70 + /* .load file hook fn to load policy */ 71 + static ssize_t profile_load(struct file *f, const char __user *buf, size_t size, 72 + loff_t *pos) 73 + { 74 + char *data; 75 + ssize_t error; 76 + 77 + data = aa_simple_write_to_buffer(OP_PROF_LOAD, buf, size, size, pos); 78 + 79 + error = PTR_ERR(data); 80 + if (!IS_ERR(data)) { 81 + error = aa_replace_profiles(data, size, PROF_ADD); 82 + kvfree(data); 83 + } 84 + 85 + return error; 86 + } 87 + 88 + static const struct file_operations aa_fs_profile_load = { 89 + .write = profile_load 90 + }; 91 + 92 + /* .replace file hook fn to load and/or replace policy */ 93 + static ssize_t profile_replace(struct file *f, const char __user *buf, 94 + size_t size, loff_t *pos) 95 + { 96 + char *data; 97 + ssize_t error; 98 + 99 + data = aa_simple_write_to_buffer(OP_PROF_REPL, buf, size, size, pos); 100 + error = PTR_ERR(data); 101 + if (!IS_ERR(data)) { 102 + error = aa_replace_profiles(data, size, PROF_REPLACE); 103 + kvfree(data); 104 + } 105 + 106 + return error; 107 + } 108 + 109 + static const struct file_operations aa_fs_profile_replace = { 110 + .write = profile_replace 111 + }; 112 + 113 + /* .remove file hook fn to remove loaded policy */ 114 + static ssize_t profile_remove(struct file *f, const char __user *buf, 115 + size_t size, loff_t *pos) 116 + { 117 + char *data; 118 + ssize_t error; 119 + 120 + /* 121 + * aa_remove_profile needs a null terminated string so 1 extra 122 + * byte is allocated and the copied data is null terminated. 123 + */ 124 + data = aa_simple_write_to_buffer(OP_PROF_RM, buf, size + 1, size, pos); 125 + 126 + error = PTR_ERR(data); 127 + if (!IS_ERR(data)) { 128 + data[size] = 0; 129 + error = aa_remove_profiles(data, size); 130 + kvfree(data); 131 + } 132 + 133 + return error; 134 + } 135 + 136 + static const struct file_operations aa_fs_profile_remove = { 137 + .write = profile_remove 138 + }; 139 + 140 + /** Base file system setup **/ 141 + 142 + static struct dentry *aa_fs_dentry __initdata; 143 + 144 + static void __init aafs_remove(const char *name) 145 + { 146 + struct dentry *dentry; 147 + 148 + dentry = lookup_one_len(name, aa_fs_dentry, strlen(name)); 149 + if (!IS_ERR(dentry)) { 150 + securityfs_remove(dentry); 151 + dput(dentry); 152 + } 153 + } 154 + 155 + /** 156 + * aafs_create - create an entry in the apparmor filesystem 157 + * @name: name of the entry (NOT NULL) 158 + * @mask: file permission mask of the file 159 + * @fops: file operations for the file (NOT NULL) 160 + * 161 + * Used aafs_remove to remove entries created with this fn. 162 + */ 163 + static int __init aafs_create(const char *name, int mask, 164 + const struct file_operations *fops) 165 + { 166 + struct dentry *dentry; 167 + 168 + dentry = securityfs_create_file(name, S_IFREG | mask, aa_fs_dentry, 169 + NULL, fops); 170 + 171 + return IS_ERR(dentry) ? PTR_ERR(dentry) : 0; 172 + } 173 + 174 + /** 175 + * aa_destroy_aafs - cleanup and free aafs 176 + * 177 + * releases dentries allocated by aa_create_aafs 178 + */ 179 + void __init aa_destroy_aafs(void) 180 + { 181 + if (aa_fs_dentry) { 182 + aafs_remove(".remove"); 183 + aafs_remove(".replace"); 184 + aafs_remove(".load"); 185 + 186 + securityfs_remove(aa_fs_dentry); 187 + aa_fs_dentry = NULL; 188 + } 189 + } 190 + 191 + /** 192 + * aa_create_aafs - create the apparmor security filesystem 193 + * 194 + * dentries created here are released by aa_destroy_aafs 195 + * 196 + * Returns: error on failure 197 + */ 198 + int __init aa_create_aafs(void) 199 + { 200 + int error; 201 + 202 + if (!apparmor_initialized) 203 + return 0; 204 + 205 + if (aa_fs_dentry) { 206 + AA_ERROR("%s: AppArmor securityfs already exists\n", __func__); 207 + return -EEXIST; 208 + } 209 + 210 + aa_fs_dentry = securityfs_create_dir("apparmor", NULL); 211 + if (IS_ERR(aa_fs_dentry)) { 212 + error = PTR_ERR(aa_fs_dentry); 213 + aa_fs_dentry = NULL; 214 + goto error; 215 + } 216 + 217 + error = aafs_create(".load", 0640, &aa_fs_profile_load); 218 + if (error) 219 + goto error; 220 + error = aafs_create(".replace", 0640, &aa_fs_profile_replace); 221 + if (error) 222 + goto error; 223 + error = aafs_create(".remove", 0640, &aa_fs_profile_remove); 224 + if (error) 225 + goto error; 226 + 227 + /* TODO: add support for apparmorfs_null and apparmorfs_mnt */ 228 + 229 + /* Report that AppArmor fs is enabled */ 230 + aa_info_message("AppArmor Filesystem Enabled"); 231 + return 0; 232 + 233 + error: 234 + aa_destroy_aafs(); 235 + AA_ERROR("Error creating AppArmor securityfs\n"); 236 + return error; 237 + } 238 + 239 + fs_initcall(aa_create_aafs);
+215
security/apparmor/audit.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor auditing functions 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #include <linux/audit.h> 16 + #include <linux/socket.h> 17 + 18 + #include "include/apparmor.h" 19 + #include "include/audit.h" 20 + #include "include/policy.h" 21 + 22 + const char *op_table[] = { 23 + "null", 24 + 25 + "sysctl", 26 + "capable", 27 + 28 + "unlink", 29 + "mkdir", 30 + "rmdir", 31 + "mknod", 32 + "truncate", 33 + "link", 34 + "symlink", 35 + "rename_src", 36 + "rename_dest", 37 + "chmod", 38 + "chown", 39 + "getattr", 40 + "open", 41 + 42 + "file_perm", 43 + "file_lock", 44 + "file_mmap", 45 + "file_mprotect", 46 + 47 + "create", 48 + "post_create", 49 + "bind", 50 + "connect", 51 + "listen", 52 + "accept", 53 + "sendmsg", 54 + "recvmsg", 55 + "getsockname", 56 + "getpeername", 57 + "getsockopt", 58 + "setsockopt", 59 + "socket_shutdown", 60 + 61 + "ptrace", 62 + 63 + "exec", 64 + "change_hat", 65 + "change_profile", 66 + "change_onexec", 67 + 68 + "setprocattr", 69 + "setrlimit", 70 + 71 + "profile_replace", 72 + "profile_load", 73 + "profile_remove" 74 + }; 75 + 76 + const char *audit_mode_names[] = { 77 + "normal", 78 + "quiet_denied", 79 + "quiet", 80 + "noquiet", 81 + "all" 82 + }; 83 + 84 + static char *aa_audit_type[] = { 85 + "AUDIT", 86 + "ALLOWED", 87 + "DENIED", 88 + "HINT", 89 + "STATUS", 90 + "ERROR", 91 + "KILLED" 92 + }; 93 + 94 + /* 95 + * Currently AppArmor auditing is fed straight into the audit framework. 96 + * 97 + * TODO: 98 + * netlink interface for complain mode 99 + * user auditing, - send user auditing to netlink interface 100 + * system control of whether user audit messages go to system log 101 + */ 102 + 103 + /** 104 + * audit_base - core AppArmor function. 105 + * @ab: audit buffer to fill (NOT NULL) 106 + * @ca: audit structure containing data to audit (NOT NULL) 107 + * 108 + * Record common AppArmor audit data from @sa 109 + */ 110 + static void audit_pre(struct audit_buffer *ab, void *ca) 111 + { 112 + struct common_audit_data *sa = ca; 113 + struct task_struct *tsk = sa->tsk ? sa->tsk : current; 114 + 115 + if (aa_g_audit_header) { 116 + audit_log_format(ab, "apparmor="); 117 + audit_log_string(ab, aa_audit_type[sa->aad.type]); 118 + } 119 + 120 + if (sa->aad.op) { 121 + audit_log_format(ab, " operation="); 122 + audit_log_string(ab, op_table[sa->aad.op]); 123 + } 124 + 125 + if (sa->aad.info) { 126 + audit_log_format(ab, " info="); 127 + audit_log_string(ab, sa->aad.info); 128 + if (sa->aad.error) 129 + audit_log_format(ab, " error=%d", sa->aad.error); 130 + } 131 + 132 + if (sa->aad.profile) { 133 + struct aa_profile *profile = sa->aad.profile; 134 + pid_t pid; 135 + rcu_read_lock(); 136 + pid = tsk->real_parent->pid; 137 + rcu_read_unlock(); 138 + audit_log_format(ab, " parent=%d", pid); 139 + if (profile->ns != root_ns) { 140 + audit_log_format(ab, " namespace="); 141 + audit_log_untrustedstring(ab, profile->ns->base.hname); 142 + } 143 + audit_log_format(ab, " profile="); 144 + audit_log_untrustedstring(ab, profile->base.hname); 145 + } 146 + 147 + if (sa->aad.name) { 148 + audit_log_format(ab, " name="); 149 + audit_log_untrustedstring(ab, sa->aad.name); 150 + } 151 + } 152 + 153 + /** 154 + * aa_audit_msg - Log a message to the audit subsystem 155 + * @sa: audit event structure (NOT NULL) 156 + * @cb: optional callback fn for type specific fields (MAYBE NULL) 157 + */ 158 + void aa_audit_msg(int type, struct common_audit_data *sa, 159 + void (*cb) (struct audit_buffer *, void *)) 160 + { 161 + sa->aad.type = type; 162 + sa->lsm_pre_audit = audit_pre; 163 + sa->lsm_post_audit = cb; 164 + common_lsm_audit(sa); 165 + } 166 + 167 + /** 168 + * aa_audit - Log a profile based audit event to the audit subsystem 169 + * @type: audit type for the message 170 + * @profile: profile to check against (NOT NULL) 171 + * @gfp: allocation flags to use 172 + * @sa: audit event (NOT NULL) 173 + * @cb: optional callback fn for type specific fields (MAYBE NULL) 174 + * 175 + * Handle default message switching based off of audit mode flags 176 + * 177 + * Returns: error on failure 178 + */ 179 + int aa_audit(int type, struct aa_profile *profile, gfp_t gfp, 180 + struct common_audit_data *sa, 181 + void (*cb) (struct audit_buffer *, void *)) 182 + { 183 + BUG_ON(!profile); 184 + 185 + if (type == AUDIT_APPARMOR_AUTO) { 186 + if (likely(!sa->aad.error)) { 187 + if (AUDIT_MODE(profile) != AUDIT_ALL) 188 + return 0; 189 + type = AUDIT_APPARMOR_AUDIT; 190 + } else if (COMPLAIN_MODE(profile)) 191 + type = AUDIT_APPARMOR_ALLOWED; 192 + else 193 + type = AUDIT_APPARMOR_DENIED; 194 + } 195 + if (AUDIT_MODE(profile) == AUDIT_QUIET || 196 + (type == AUDIT_APPARMOR_DENIED && 197 + AUDIT_MODE(profile) == AUDIT_QUIET)) 198 + return sa->aad.error; 199 + 200 + if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED) 201 + type = AUDIT_APPARMOR_KILL; 202 + 203 + if (!unconfined(profile)) 204 + sa->aad.profile = profile; 205 + 206 + aa_audit_msg(type, sa, cb); 207 + 208 + if (sa->aad.type == AUDIT_APPARMOR_KILL) 209 + (void)send_sig_info(SIGKILL, NULL, sa->tsk ? sa->tsk : current); 210 + 211 + if (sa->aad.type == AUDIT_APPARMOR_ALLOWED) 212 + return complain_error(sa->aad.error); 213 + 214 + return sa->aad.error; 215 + }
+141
security/apparmor/capability.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor capability mediation functions 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #include <linux/capability.h> 16 + #include <linux/errno.h> 17 + #include <linux/gfp.h> 18 + 19 + #include "include/apparmor.h" 20 + #include "include/capability.h" 21 + #include "include/context.h" 22 + #include "include/policy.h" 23 + #include "include/audit.h" 24 + 25 + /* 26 + * Table of capability names: we generate it from capabilities.h. 27 + */ 28 + #include "capability_names.h" 29 + 30 + struct audit_cache { 31 + struct aa_profile *profile; 32 + kernel_cap_t caps; 33 + }; 34 + 35 + static DEFINE_PER_CPU(struct audit_cache, audit_cache); 36 + 37 + /** 38 + * audit_cb - call back for capability components of audit struct 39 + * @ab - audit buffer (NOT NULL) 40 + * @va - audit struct to audit data from (NOT NULL) 41 + */ 42 + static void audit_cb(struct audit_buffer *ab, void *va) 43 + { 44 + struct common_audit_data *sa = va; 45 + audit_log_format(ab, " capname="); 46 + audit_log_untrustedstring(ab, capability_names[sa->u.cap]); 47 + } 48 + 49 + /** 50 + * audit_caps - audit a capability 51 + * @profile: profile confining task (NOT NULL) 52 + * @task: task capability test was performed against (NOT NULL) 53 + * @cap: capability tested 54 + * @error: error code returned by test 55 + * 56 + * Do auditing of capability and handle, audit/complain/kill modes switching 57 + * and duplicate message elimination. 58 + * 59 + * Returns: 0 or sa->error on success, error code on failure 60 + */ 61 + static int audit_caps(struct aa_profile *profile, struct task_struct *task, 62 + int cap, int error) 63 + { 64 + struct audit_cache *ent; 65 + int type = AUDIT_APPARMOR_AUTO; 66 + struct common_audit_data sa; 67 + COMMON_AUDIT_DATA_INIT(&sa, CAP); 68 + sa.tsk = task; 69 + sa.u.cap = cap; 70 + sa.aad.op = OP_CAPABLE; 71 + sa.aad.error = error; 72 + 73 + if (likely(!error)) { 74 + /* test if auditing is being forced */ 75 + if (likely((AUDIT_MODE(profile) != AUDIT_ALL) && 76 + !cap_raised(profile->caps.audit, cap))) 77 + return 0; 78 + type = AUDIT_APPARMOR_AUDIT; 79 + } else if (KILL_MODE(profile) || 80 + cap_raised(profile->caps.kill, cap)) { 81 + type = AUDIT_APPARMOR_KILL; 82 + } else if (cap_raised(profile->caps.quiet, cap) && 83 + AUDIT_MODE(profile) != AUDIT_NOQUIET && 84 + AUDIT_MODE(profile) != AUDIT_ALL) { 85 + /* quiet auditing */ 86 + return error; 87 + } 88 + 89 + /* Do simple duplicate message elimination */ 90 + ent = &get_cpu_var(audit_cache); 91 + if (profile == ent->profile && cap_raised(ent->caps, cap)) { 92 + put_cpu_var(audit_cache); 93 + if (COMPLAIN_MODE(profile)) 94 + return complain_error(error); 95 + return error; 96 + } else { 97 + aa_put_profile(ent->profile); 98 + ent->profile = aa_get_profile(profile); 99 + cap_raise(ent->caps, cap); 100 + } 101 + put_cpu_var(audit_cache); 102 + 103 + return aa_audit(type, profile, GFP_ATOMIC, &sa, audit_cb); 104 + } 105 + 106 + /** 107 + * profile_capable - test if profile allows use of capability @cap 108 + * @profile: profile being enforced (NOT NULL, NOT unconfined) 109 + * @cap: capability to test if allowed 110 + * 111 + * Returns: 0 if allowed else -EPERM 112 + */ 113 + static int profile_capable(struct aa_profile *profile, int cap) 114 + { 115 + return cap_raised(profile->caps.allow, cap) ? 0 : -EPERM; 116 + } 117 + 118 + /** 119 + * aa_capable - test permission to use capability 120 + * @task: task doing capability test against (NOT NULL) 121 + * @profile: profile confining @task (NOT NULL) 122 + * @cap: capability to be tested 123 + * @audit: whether an audit record should be generated 124 + * 125 + * Look up capability in profile capability set. 126 + * 127 + * Returns: 0 on success, or else an error code. 128 + */ 129 + int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap, 130 + int audit) 131 + { 132 + int error = profile_capable(profile, cap); 133 + 134 + if (!audit) { 135 + if (COMPLAIN_MODE(profile)) 136 + return complain_error(error); 137 + return error; 138 + } 139 + 140 + return audit_caps(profile, task, cap, error); 141 + }
+216
security/apparmor/context.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor functions used to manipulate object security 5 + * contexts. 6 + * 7 + * Copyright (C) 1998-2008 Novell/SUSE 8 + * Copyright 2009-2010 Canonical Ltd. 9 + * 10 + * This program is free software; you can redistribute it and/or 11 + * modify it under the terms of the GNU General Public License as 12 + * published by the Free Software Foundation, version 2 of the 13 + * License. 14 + * 15 + * 16 + * AppArmor sets confinement on every task, via the the aa_task_cxt and 17 + * the aa_task_cxt.profile, both of which are required and are not allowed 18 + * to be NULL. The aa_task_cxt is not reference counted and is unique 19 + * to each cred (which is reference count). The profile pointed to by 20 + * the task_cxt is reference counted. 21 + * 22 + * TODO 23 + * If a task uses change_hat it currently does not return to the old 24 + * cred or task context but instead creates a new one. Ideally the task 25 + * should return to the previous cred if it has not been modified. 26 + * 27 + */ 28 + 29 + #include "include/context.h" 30 + #include "include/policy.h" 31 + 32 + /** 33 + * aa_alloc_task_context - allocate a new task_cxt 34 + * @flags: gfp flags for allocation 35 + * 36 + * Returns: allocated buffer or NULL on failure 37 + */ 38 + struct aa_task_cxt *aa_alloc_task_context(gfp_t flags) 39 + { 40 + return kzalloc(sizeof(struct aa_task_cxt), flags); 41 + } 42 + 43 + /** 44 + * aa_free_task_context - free a task_cxt 45 + * @cxt: task_cxt to free (MAYBE NULL) 46 + */ 47 + void aa_free_task_context(struct aa_task_cxt *cxt) 48 + { 49 + if (cxt) { 50 + aa_put_profile(cxt->profile); 51 + aa_put_profile(cxt->previous); 52 + aa_put_profile(cxt->onexec); 53 + 54 + kzfree(cxt); 55 + } 56 + } 57 + 58 + /** 59 + * aa_dup_task_context - duplicate a task context, incrementing reference counts 60 + * @new: a blank task context (NOT NULL) 61 + * @old: the task context to copy (NOT NULL) 62 + */ 63 + void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old) 64 + { 65 + *new = *old; 66 + aa_get_profile(new->profile); 67 + aa_get_profile(new->previous); 68 + aa_get_profile(new->onexec); 69 + } 70 + 71 + /** 72 + * aa_replace_current_profile - replace the current tasks profiles 73 + * @profile: new profile (NOT NULL) 74 + * 75 + * Returns: 0 or error on failure 76 + */ 77 + int aa_replace_current_profile(struct aa_profile *profile) 78 + { 79 + struct aa_task_cxt *cxt = current_cred()->security; 80 + struct cred *new; 81 + BUG_ON(!profile); 82 + 83 + if (cxt->profile == profile) 84 + return 0; 85 + 86 + new = prepare_creds(); 87 + if (!new) 88 + return -ENOMEM; 89 + 90 + cxt = new->security; 91 + if (unconfined(profile) || (cxt->profile->ns != profile->ns)) { 92 + /* if switching to unconfined or a different profile namespace 93 + * clear out context state 94 + */ 95 + aa_put_profile(cxt->previous); 96 + aa_put_profile(cxt->onexec); 97 + cxt->previous = NULL; 98 + cxt->onexec = NULL; 99 + cxt->token = 0; 100 + } 101 + /* be careful switching cxt->profile, when racing replacement it 102 + * is possible that cxt->profile->replacedby is the reference keeping 103 + * @profile valid, so make sure to get its reference before dropping 104 + * the reference on cxt->profile */ 105 + aa_get_profile(profile); 106 + aa_put_profile(cxt->profile); 107 + cxt->profile = profile; 108 + 109 + commit_creds(new); 110 + return 0; 111 + } 112 + 113 + /** 114 + * aa_set_current_onexec - set the tasks change_profile to happen onexec 115 + * @profile: system profile to set at exec (MAYBE NULL to clear value) 116 + * 117 + * Returns: 0 or error on failure 118 + */ 119 + int aa_set_current_onexec(struct aa_profile *profile) 120 + { 121 + struct aa_task_cxt *cxt; 122 + struct cred *new = prepare_creds(); 123 + if (!new) 124 + return -ENOMEM; 125 + 126 + cxt = new->security; 127 + aa_get_profile(profile); 128 + aa_put_profile(cxt->onexec); 129 + cxt->onexec = profile; 130 + 131 + commit_creds(new); 132 + return 0; 133 + } 134 + 135 + /** 136 + * aa_set_current_hat - set the current tasks hat 137 + * @profile: profile to set as the current hat (NOT NULL) 138 + * @token: token value that must be specified to change from the hat 139 + * 140 + * Do switch of tasks hat. If the task is currently in a hat 141 + * validate the token to match. 142 + * 143 + * Returns: 0 or error on failure 144 + */ 145 + int aa_set_current_hat(struct aa_profile *profile, u64 token) 146 + { 147 + struct aa_task_cxt *cxt; 148 + struct cred *new = prepare_creds(); 149 + if (!new) 150 + return -ENOMEM; 151 + BUG_ON(!profile); 152 + 153 + cxt = new->security; 154 + if (!cxt->previous) { 155 + /* transfer refcount */ 156 + cxt->previous = cxt->profile; 157 + cxt->token = token; 158 + } else if (cxt->token == token) { 159 + aa_put_profile(cxt->profile); 160 + } else { 161 + /* previous_profile && cxt->token != token */ 162 + abort_creds(new); 163 + return -EACCES; 164 + } 165 + cxt->profile = aa_get_profile(aa_newest_version(profile)); 166 + /* clear exec on switching context */ 167 + aa_put_profile(cxt->onexec); 168 + cxt->onexec = NULL; 169 + 170 + commit_creds(new); 171 + return 0; 172 + } 173 + 174 + /** 175 + * aa_restore_previous_profile - exit from hat context restoring the profile 176 + * @token: the token that must be matched to exit hat context 177 + * 178 + * Attempt to return out of a hat to the previous profile. The token 179 + * must match the stored token value. 180 + * 181 + * Returns: 0 or error of failure 182 + */ 183 + int aa_restore_previous_profile(u64 token) 184 + { 185 + struct aa_task_cxt *cxt; 186 + struct cred *new = prepare_creds(); 187 + if (!new) 188 + return -ENOMEM; 189 + 190 + cxt = new->security; 191 + if (cxt->token != token) { 192 + abort_creds(new); 193 + return -EACCES; 194 + } 195 + /* ignore restores when there is no saved profile */ 196 + if (!cxt->previous) { 197 + abort_creds(new); 198 + return 0; 199 + } 200 + 201 + aa_put_profile(cxt->profile); 202 + cxt->profile = aa_newest_version(cxt->previous); 203 + BUG_ON(!cxt->profile); 204 + if (unlikely(cxt->profile != cxt->previous)) { 205 + aa_get_profile(cxt->profile); 206 + aa_put_profile(cxt->previous); 207 + } 208 + /* clear exec && prev information when restoring to previous context */ 209 + cxt->previous = NULL; 210 + cxt->token = 0; 211 + aa_put_profile(cxt->onexec); 212 + cxt->onexec = NULL; 213 + 214 + commit_creds(new); 215 + return 0; 216 + }
+823
security/apparmor/domain.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor policy attachment and domain transitions 5 + * 6 + * Copyright (C) 2002-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #include <linux/errno.h> 16 + #include <linux/fdtable.h> 17 + #include <linux/file.h> 18 + #include <linux/mount.h> 19 + #include <linux/syscalls.h> 20 + #include <linux/tracehook.h> 21 + #include <linux/personality.h> 22 + 23 + #include "include/audit.h" 24 + #include "include/apparmorfs.h" 25 + #include "include/context.h" 26 + #include "include/domain.h" 27 + #include "include/file.h" 28 + #include "include/ipc.h" 29 + #include "include/match.h" 30 + #include "include/path.h" 31 + #include "include/policy.h" 32 + 33 + /** 34 + * aa_free_domain_entries - free entries in a domain table 35 + * @domain: the domain table to free (MAYBE NULL) 36 + */ 37 + void aa_free_domain_entries(struct aa_domain *domain) 38 + { 39 + int i; 40 + if (domain) { 41 + if (!domain->table) 42 + return; 43 + 44 + for (i = 0; i < domain->size; i++) 45 + kzfree(domain->table[i]); 46 + kzfree(domain->table); 47 + domain->table = NULL; 48 + } 49 + } 50 + 51 + /** 52 + * may_change_ptraced_domain - check if can change profile on ptraced task 53 + * @task: task we want to change profile of (NOT NULL) 54 + * @to_profile: profile to change to (NOT NULL) 55 + * 56 + * Check if the task is ptraced and if so if the tracing task is allowed 57 + * to trace the new domain 58 + * 59 + * Returns: %0 or error if change not allowed 60 + */ 61 + static int may_change_ptraced_domain(struct task_struct *task, 62 + struct aa_profile *to_profile) 63 + { 64 + struct task_struct *tracer; 65 + const struct cred *cred = NULL; 66 + struct aa_profile *tracerp = NULL; 67 + int error = 0; 68 + 69 + rcu_read_lock(); 70 + tracer = tracehook_tracer_task(task); 71 + if (tracer) { 72 + /* released below */ 73 + cred = get_task_cred(tracer); 74 + tracerp = aa_cred_profile(cred); 75 + } 76 + rcu_read_unlock(); 77 + 78 + /* not ptraced */ 79 + if (!tracer || unconfined(tracerp)) 80 + goto out; 81 + 82 + error = aa_may_ptrace(tracer, tracerp, to_profile, PTRACE_MODE_ATTACH); 83 + 84 + out: 85 + if (cred) 86 + put_cred(cred); 87 + 88 + return error; 89 + } 90 + 91 + /** 92 + * change_profile_perms - find permissions for change_profile 93 + * @profile: the current profile (NOT NULL) 94 + * @ns: the namespace being switched to (NOT NULL) 95 + * @name: the name of the profile to change to (NOT NULL) 96 + * @request: requested perms 97 + * @start: state to start matching in 98 + * 99 + * Returns: permission set 100 + */ 101 + static struct file_perms change_profile_perms(struct aa_profile *profile, 102 + struct aa_namespace *ns, 103 + const char *name, u32 request, 104 + unsigned int start) 105 + { 106 + struct file_perms perms; 107 + struct path_cond cond = { }; 108 + unsigned int state; 109 + 110 + if (unconfined(profile)) { 111 + perms.allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC; 112 + perms.audit = perms.quiet = perms.kill = 0; 113 + return perms; 114 + } else if (!profile->file.dfa) { 115 + return nullperms; 116 + } else if ((ns == profile->ns)) { 117 + /* try matching against rules with out namespace prepended */ 118 + aa_str_perms(profile->file.dfa, start, name, &cond, &perms); 119 + if (COMBINED_PERM_MASK(perms) & request) 120 + return perms; 121 + } 122 + 123 + /* try matching with namespace name and then profile */ 124 + state = aa_dfa_match(profile->file.dfa, start, ns->base.name); 125 + state = aa_dfa_match_len(profile->file.dfa, state, ":", 1); 126 + aa_str_perms(profile->file.dfa, state, name, &cond, &perms); 127 + 128 + return perms; 129 + } 130 + 131 + /** 132 + * __attach_match_ - find an attachment match 133 + * @name - to match against (NOT NULL) 134 + * @head - profile list to walk (NOT NULL) 135 + * 136 + * Do a linear search on the profiles in the list. There is a matching 137 + * preference where an exact match is preferred over a name which uses 138 + * expressions to match, and matching expressions with the greatest 139 + * xmatch_len are preferred. 140 + * 141 + * Requires: @head not be shared or have appropriate locks held 142 + * 143 + * Returns: profile or NULL if no match found 144 + */ 145 + static struct aa_profile *__attach_match(const char *name, 146 + struct list_head *head) 147 + { 148 + int len = 0; 149 + struct aa_profile *profile, *candidate = NULL; 150 + 151 + list_for_each_entry(profile, head, base.list) { 152 + if (profile->flags & PFLAG_NULL) 153 + continue; 154 + if (profile->xmatch && profile->xmatch_len > len) { 155 + unsigned int state = aa_dfa_match(profile->xmatch, 156 + DFA_START, name); 157 + u32 perm = dfa_user_allow(profile->xmatch, state); 158 + /* any accepting state means a valid match. */ 159 + if (perm & MAY_EXEC) { 160 + candidate = profile; 161 + len = profile->xmatch_len; 162 + } 163 + } else if (!strcmp(profile->base.name, name)) 164 + /* exact non-re match, no more searching required */ 165 + return profile; 166 + } 167 + 168 + return candidate; 169 + } 170 + 171 + /** 172 + * find_attach - do attachment search for unconfined processes 173 + * @ns: the current namespace (NOT NULL) 174 + * @list: list to search (NOT NULL) 175 + * @name: the executable name to match against (NOT NULL) 176 + * 177 + * Returns: profile or NULL if no match found 178 + */ 179 + static struct aa_profile *find_attach(struct aa_namespace *ns, 180 + struct list_head *list, const char *name) 181 + { 182 + struct aa_profile *profile; 183 + 184 + read_lock(&ns->lock); 185 + profile = aa_get_profile(__attach_match(name, list)); 186 + read_unlock(&ns->lock); 187 + 188 + return profile; 189 + } 190 + 191 + /** 192 + * separate_fqname - separate the namespace and profile names 193 + * @fqname: the fqname name to split (NOT NULL) 194 + * @ns_name: the namespace name if it exists (NOT NULL) 195 + * 196 + * This is the xtable equivalent routine of aa_split_fqname. It finds the 197 + * split in an xtable fqname which contains an embedded \0 instead of a : 198 + * if a namespace is specified. This is done so the xtable is constant and 199 + * isn't re-split on every lookup. 200 + * 201 + * Either the profile or namespace name may be optional but if the namespace 202 + * is specified the profile name termination must be present. This results 203 + * in the following possible encodings: 204 + * profile_name\0 205 + * :ns_name\0profile_name\0 206 + * :ns_name\0\0 207 + * 208 + * NOTE: the xtable fqname is pre-validated at load time in unpack_trans_table 209 + * 210 + * Returns: profile name if it is specified else NULL 211 + */ 212 + static const char *separate_fqname(const char *fqname, const char **ns_name) 213 + { 214 + const char *name; 215 + 216 + if (fqname[0] == ':') { 217 + /* In this case there is guaranteed to be two \0 terminators 218 + * in the string. They are verified at load time by 219 + * by unpack_trans_table 220 + */ 221 + *ns_name = fqname + 1; /* skip : */ 222 + name = *ns_name + strlen(*ns_name) + 1; 223 + if (!*name) 224 + name = NULL; 225 + } else { 226 + *ns_name = NULL; 227 + name = fqname; 228 + } 229 + 230 + return name; 231 + } 232 + 233 + static const char *next_name(int xtype, const char *name) 234 + { 235 + return NULL; 236 + } 237 + 238 + /** 239 + * x_table_lookup - lookup an x transition name via transition table 240 + * @profile: current profile (NOT NULL) 241 + * @xindex: index into x transition table 242 + * 243 + * Returns: refcounted profile, or NULL on failure (MAYBE NULL) 244 + */ 245 + static struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex) 246 + { 247 + struct aa_profile *new_profile = NULL; 248 + struct aa_namespace *ns = profile->ns; 249 + u32 xtype = xindex & AA_X_TYPE_MASK; 250 + int index = xindex & AA_X_INDEX_MASK; 251 + const char *name; 252 + 253 + /* index is guaranteed to be in range, validated at load time */ 254 + for (name = profile->file.trans.table[index]; !new_profile && name; 255 + name = next_name(xtype, name)) { 256 + struct aa_namespace *new_ns; 257 + const char *xname = NULL; 258 + 259 + new_ns = NULL; 260 + if (xindex & AA_X_CHILD) { 261 + /* release by caller */ 262 + new_profile = aa_find_child(profile, name); 263 + continue; 264 + } else if (*name == ':') { 265 + /* switching namespace */ 266 + const char *ns_name; 267 + xname = name = separate_fqname(name, &ns_name); 268 + if (!xname) 269 + /* no name so use profile name */ 270 + xname = profile->base.hname; 271 + if (*ns_name == '@') { 272 + /* TODO: variable support */ 273 + ; 274 + } 275 + /* released below */ 276 + new_ns = aa_find_namespace(ns, ns_name); 277 + if (!new_ns) 278 + continue; 279 + } else if (*name == '@') { 280 + /* TODO: variable support */ 281 + continue; 282 + } else { 283 + /* basic namespace lookup */ 284 + xname = name; 285 + } 286 + 287 + /* released by caller */ 288 + new_profile = aa_lookup_profile(new_ns ? new_ns : ns, xname); 289 + aa_put_namespace(new_ns); 290 + } 291 + 292 + /* released by caller */ 293 + return new_profile; 294 + } 295 + 296 + /** 297 + * x_to_profile - get target profile for a given xindex 298 + * @profile: current profile (NOT NULL) 299 + * @name: name to lookup (NOT NULL) 300 + * @xindex: index into x transition table 301 + * 302 + * find profile for a transition index 303 + * 304 + * Returns: refcounted profile or NULL if not found available 305 + */ 306 + static struct aa_profile *x_to_profile(struct aa_profile *profile, 307 + const char *name, u32 xindex) 308 + { 309 + struct aa_profile *new_profile = NULL; 310 + struct aa_namespace *ns = profile->ns; 311 + u32 xtype = xindex & AA_X_TYPE_MASK; 312 + 313 + switch (xtype) { 314 + case AA_X_NONE: 315 + /* fail exec unless ix || ux fallback - handled by caller */ 316 + return NULL; 317 + case AA_X_NAME: 318 + if (xindex & AA_X_CHILD) 319 + /* released by caller */ 320 + new_profile = find_attach(ns, &profile->base.profiles, 321 + name); 322 + else 323 + /* released by caller */ 324 + new_profile = find_attach(ns, &ns->base.profiles, 325 + name); 326 + break; 327 + case AA_X_TABLE: 328 + /* released by caller */ 329 + new_profile = x_table_lookup(profile, xindex); 330 + break; 331 + } 332 + 333 + /* released by caller */ 334 + return new_profile; 335 + } 336 + 337 + /** 338 + * apparmor_bprm_set_creds - set the new creds on the bprm struct 339 + * @bprm: binprm for the exec (NOT NULL) 340 + * 341 + * Returns: %0 or error on failure 342 + */ 343 + int apparmor_bprm_set_creds(struct linux_binprm *bprm) 344 + { 345 + struct aa_task_cxt *cxt; 346 + struct aa_profile *profile, *new_profile = NULL; 347 + struct aa_namespace *ns; 348 + char *buffer = NULL; 349 + unsigned int state; 350 + struct file_perms perms = {}; 351 + struct path_cond cond = { 352 + bprm->file->f_path.dentry->d_inode->i_uid, 353 + bprm->file->f_path.dentry->d_inode->i_mode 354 + }; 355 + const char *name = NULL, *target = NULL, *info = NULL; 356 + int error = cap_bprm_set_creds(bprm); 357 + if (error) 358 + return error; 359 + 360 + if (bprm->cred_prepared) 361 + return 0; 362 + 363 + cxt = bprm->cred->security; 364 + BUG_ON(!cxt); 365 + 366 + profile = aa_get_profile(aa_newest_version(cxt->profile)); 367 + /* 368 + * get the namespace from the replacement profile as replacement 369 + * can change the namespace 370 + */ 371 + ns = profile->ns; 372 + state = profile->file.start; 373 + 374 + /* buffer freed below, name is pointer into buffer */ 375 + error = aa_get_name(&bprm->file->f_path, profile->path_flags, &buffer, 376 + &name); 377 + if (error) { 378 + if (profile->flags & 379 + (PFLAG_IX_ON_NAME_ERROR | PFLAG_UNCONFINED)) 380 + error = 0; 381 + info = "Exec failed name resolution"; 382 + name = bprm->filename; 383 + goto audit; 384 + } 385 + 386 + /* Test for onexec first as onexec directives override other 387 + * x transitions. 388 + */ 389 + if (unconfined(profile)) { 390 + /* unconfined task */ 391 + if (cxt->onexec) 392 + /* change_profile on exec already been granted */ 393 + new_profile = aa_get_profile(cxt->onexec); 394 + else 395 + new_profile = find_attach(ns, &ns->base.profiles, name); 396 + if (!new_profile) 397 + goto cleanup; 398 + goto apply; 399 + } 400 + 401 + /* find exec permissions for name */ 402 + state = aa_str_perms(profile->file.dfa, state, name, &cond, &perms); 403 + if (cxt->onexec) { 404 + struct file_perms cp; 405 + info = "change_profile onexec"; 406 + if (!(perms.allow & AA_MAY_ONEXEC)) 407 + goto audit; 408 + 409 + /* test if this exec can be paired with change_profile onexec. 410 + * onexec permission is linked to exec with a standard pairing 411 + * exec\0change_profile 412 + */ 413 + state = aa_dfa_null_transition(profile->file.dfa, state); 414 + cp = change_profile_perms(profile, cxt->onexec->ns, name, 415 + AA_MAY_ONEXEC, state); 416 + 417 + if (!(cp.allow & AA_MAY_ONEXEC)) 418 + goto audit; 419 + new_profile = aa_get_profile(aa_newest_version(cxt->onexec)); 420 + goto apply; 421 + } 422 + 423 + if (perms.allow & MAY_EXEC) { 424 + /* exec permission determine how to transition */ 425 + new_profile = x_to_profile(profile, name, perms.xindex); 426 + if (!new_profile) { 427 + if (perms.xindex & AA_X_INHERIT) { 428 + /* (p|c|n)ix - don't change profile but do 429 + * use the newest version, which was picked 430 + * up above when getting profile 431 + */ 432 + info = "ix fallback"; 433 + new_profile = aa_get_profile(profile); 434 + goto x_clear; 435 + } else if (perms.xindex & AA_X_UNCONFINED) { 436 + new_profile = aa_get_profile(ns->unconfined); 437 + info = "ux fallback"; 438 + } else { 439 + error = -ENOENT; 440 + info = "profile not found"; 441 + } 442 + } 443 + } else if (COMPLAIN_MODE(profile)) { 444 + /* no exec permission - are we in learning mode */ 445 + new_profile = aa_new_null_profile(profile, 0); 446 + if (!new_profile) { 447 + error = -ENOMEM; 448 + info = "could not create null profile"; 449 + } else { 450 + error = -EACCES; 451 + target = new_profile->base.hname; 452 + } 453 + perms.xindex |= AA_X_UNSAFE; 454 + } else 455 + /* fail exec */ 456 + error = -EACCES; 457 + 458 + if (!new_profile) 459 + goto audit; 460 + 461 + if (bprm->unsafe & LSM_UNSAFE_SHARE) { 462 + /* FIXME: currently don't mediate shared state */ 463 + ; 464 + } 465 + 466 + if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { 467 + error = may_change_ptraced_domain(current, new_profile); 468 + if (error) { 469 + aa_put_profile(new_profile); 470 + goto audit; 471 + } 472 + } 473 + 474 + /* Determine if secure exec is needed. 475 + * Can be at this point for the following reasons: 476 + * 1. unconfined switching to confined 477 + * 2. confined switching to different confinement 478 + * 3. confined switching to unconfined 479 + * 480 + * Cases 2 and 3 are marked as requiring secure exec 481 + * (unless policy specified "unsafe exec") 482 + * 483 + * bprm->unsafe is used to cache the AA_X_UNSAFE permission 484 + * to avoid having to recompute in secureexec 485 + */ 486 + if (!(perms.xindex & AA_X_UNSAFE)) { 487 + AA_DEBUG("scrubbing environment variables for %s profile=%s\n", 488 + name, new_profile->base.hname); 489 + bprm->unsafe |= AA_SECURE_X_NEEDED; 490 + } 491 + apply: 492 + target = new_profile->base.hname; 493 + /* when transitioning profiles clear unsafe personality bits */ 494 + bprm->per_clear |= PER_CLEAR_ON_SETID; 495 + 496 + x_clear: 497 + aa_put_profile(cxt->profile); 498 + /* transfer new profile reference will be released when cxt is freed */ 499 + cxt->profile = new_profile; 500 + 501 + /* clear out all temporary/transitional state from the context */ 502 + aa_put_profile(cxt->previous); 503 + aa_put_profile(cxt->onexec); 504 + cxt->previous = NULL; 505 + cxt->onexec = NULL; 506 + cxt->token = 0; 507 + 508 + audit: 509 + error = aa_audit_file(profile, &perms, GFP_KERNEL, OP_EXEC, MAY_EXEC, 510 + name, target, cond.uid, info, error); 511 + 512 + cleanup: 513 + aa_put_profile(profile); 514 + kfree(buffer); 515 + 516 + return error; 517 + } 518 + 519 + /** 520 + * apparmor_bprm_secureexec - determine if secureexec is needed 521 + * @bprm: binprm for exec (NOT NULL) 522 + * 523 + * Returns: %1 if secureexec is needed else %0 524 + */ 525 + int apparmor_bprm_secureexec(struct linux_binprm *bprm) 526 + { 527 + int ret = cap_bprm_secureexec(bprm); 528 + 529 + /* the decision to use secure exec is computed in set_creds 530 + * and stored in bprm->unsafe. 531 + */ 532 + if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED)) 533 + ret = 1; 534 + 535 + return ret; 536 + } 537 + 538 + /** 539 + * apparmor_bprm_committing_creds - do task cleanup on committing new creds 540 + * @bprm: binprm for the exec (NOT NULL) 541 + */ 542 + void apparmor_bprm_committing_creds(struct linux_binprm *bprm) 543 + { 544 + struct aa_profile *profile = __aa_current_profile(); 545 + struct aa_task_cxt *new_cxt = bprm->cred->security; 546 + 547 + /* bail out if unconfined or not changing profile */ 548 + if ((new_cxt->profile == profile) || 549 + (unconfined(new_cxt->profile))) 550 + return; 551 + 552 + current->pdeath_signal = 0; 553 + 554 + /* reset soft limits and set hard limits for the new profile */ 555 + __aa_transition_rlimits(profile, new_cxt->profile); 556 + } 557 + 558 + /** 559 + * apparmor_bprm_commited_cred - do cleanup after new creds committed 560 + * @bprm: binprm for the exec (NOT NULL) 561 + */ 562 + void apparmor_bprm_committed_creds(struct linux_binprm *bprm) 563 + { 564 + /* TODO: cleanup signals - ipc mediation */ 565 + return; 566 + } 567 + 568 + /* 569 + * Functions for self directed profile change 570 + */ 571 + 572 + /** 573 + * new_compound_name - create an hname with @n2 appended to @n1 574 + * @n1: base of hname (NOT NULL) 575 + * @n2: name to append (NOT NULL) 576 + * 577 + * Returns: new name or NULL on error 578 + */ 579 + static char *new_compound_name(const char *n1, const char *n2) 580 + { 581 + char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL); 582 + if (name) 583 + sprintf(name, "%s//%s", n1, n2); 584 + return name; 585 + } 586 + 587 + /** 588 + * aa_change_hat - change hat to/from subprofile 589 + * @hats: vector of hat names to try changing into (MAYBE NULL if @count == 0) 590 + * @count: number of hat names in @hats 591 + * @token: magic value to validate the hat change 592 + * @permtest: true if this is just a permission test 593 + * 594 + * Change to the first profile specified in @hats that exists, and store 595 + * the @hat_magic in the current task context. If the count == 0 and the 596 + * @token matches that stored in the current task context, return to the 597 + * top level profile. 598 + * 599 + * Returns %0 on success, error otherwise. 600 + */ 601 + int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) 602 + { 603 + const struct cred *cred; 604 + struct aa_task_cxt *cxt; 605 + struct aa_profile *profile, *previous_profile, *hat = NULL; 606 + char *name = NULL; 607 + int i; 608 + struct file_perms perms = {}; 609 + const char *target = NULL, *info = NULL; 610 + int error = 0; 611 + 612 + /* released below */ 613 + cred = get_current_cred(); 614 + cxt = cred->security; 615 + profile = aa_cred_profile(cred); 616 + previous_profile = cxt->previous; 617 + 618 + if (unconfined(profile)) { 619 + info = "unconfined"; 620 + error = -EPERM; 621 + goto audit; 622 + } 623 + 624 + if (count) { 625 + /* attempting to change into a new hat or switch to a sibling */ 626 + struct aa_profile *root; 627 + root = PROFILE_IS_HAT(profile) ? profile->parent : profile; 628 + 629 + /* find first matching hat */ 630 + for (i = 0; i < count && !hat; i++) 631 + /* released below */ 632 + hat = aa_find_child(root, hats[i]); 633 + if (!hat) { 634 + if (!COMPLAIN_MODE(root) || permtest) { 635 + if (list_empty(&root->base.profiles)) 636 + error = -ECHILD; 637 + else 638 + error = -ENOENT; 639 + goto out; 640 + } 641 + 642 + /* 643 + * In complain mode and failed to match any hats. 644 + * Audit the failure is based off of the first hat 645 + * supplied. This is done due how userspace 646 + * interacts with change_hat. 647 + * 648 + * TODO: Add logging of all failed hats 649 + */ 650 + 651 + /* freed below */ 652 + name = new_compound_name(root->base.hname, hats[0]); 653 + target = name; 654 + /* released below */ 655 + hat = aa_new_null_profile(profile, 1); 656 + if (!hat) { 657 + info = "failed null profile create"; 658 + error = -ENOMEM; 659 + goto audit; 660 + } 661 + } else { 662 + target = hat->base.hname; 663 + if (!PROFILE_IS_HAT(hat)) { 664 + info = "target not hat"; 665 + error = -EPERM; 666 + goto audit; 667 + } 668 + } 669 + 670 + error = may_change_ptraced_domain(current, hat); 671 + if (error) { 672 + info = "ptraced"; 673 + error = -EPERM; 674 + goto audit; 675 + } 676 + 677 + if (!permtest) { 678 + error = aa_set_current_hat(hat, token); 679 + if (error == -EACCES) 680 + /* kill task in case of brute force attacks */ 681 + perms.kill = AA_MAY_CHANGEHAT; 682 + else if (name && !error) 683 + /* reset error for learning of new hats */ 684 + error = -ENOENT; 685 + } 686 + } else if (previous_profile) { 687 + /* Return to saved profile. Kill task if restore fails 688 + * to avoid brute force attacks 689 + */ 690 + target = previous_profile->base.hname; 691 + error = aa_restore_previous_profile(token); 692 + perms.kill = AA_MAY_CHANGEHAT; 693 + } else 694 + /* ignore restores when there is no saved profile */ 695 + goto out; 696 + 697 + audit: 698 + if (!permtest) 699 + error = aa_audit_file(profile, &perms, GFP_KERNEL, 700 + OP_CHANGE_HAT, AA_MAY_CHANGEHAT, NULL, 701 + target, 0, info, error); 702 + 703 + out: 704 + aa_put_profile(hat); 705 + kfree(name); 706 + put_cred(cred); 707 + 708 + return error; 709 + } 710 + 711 + /** 712 + * aa_change_profile - perform a one-way profile transition 713 + * @ns_name: name of the profile namespace to change to (MAYBE NULL) 714 + * @hname: name of profile to change to (MAYBE NULL) 715 + * @onexec: whether this transition is to take place immediately or at exec 716 + * @permtest: true if this is just a permission test 717 + * 718 + * Change to new profile @name. Unlike with hats, there is no way 719 + * to change back. If @name isn't specified the current profile name is 720 + * used. 721 + * If @onexec then the transition is delayed until 722 + * the next exec. 723 + * 724 + * Returns %0 on success, error otherwise. 725 + */ 726 + int aa_change_profile(const char *ns_name, const char *hname, bool onexec, 727 + bool permtest) 728 + { 729 + const struct cred *cred; 730 + struct aa_task_cxt *cxt; 731 + struct aa_profile *profile, *target = NULL; 732 + struct aa_namespace *ns = NULL; 733 + struct file_perms perms = {}; 734 + const char *name = NULL, *info = NULL; 735 + int op, error = 0; 736 + u32 request; 737 + 738 + if (!hname && !ns_name) 739 + return -EINVAL; 740 + 741 + if (onexec) { 742 + request = AA_MAY_ONEXEC; 743 + op = OP_CHANGE_ONEXEC; 744 + } else { 745 + request = AA_MAY_CHANGE_PROFILE; 746 + op = OP_CHANGE_PROFILE; 747 + } 748 + 749 + cred = get_current_cred(); 750 + cxt = cred->security; 751 + profile = aa_cred_profile(cred); 752 + 753 + if (ns_name) { 754 + /* released below */ 755 + ns = aa_find_namespace(profile->ns, ns_name); 756 + if (!ns) { 757 + /* we don't create new namespace in complain mode */ 758 + name = ns_name; 759 + info = "namespace not found"; 760 + error = -ENOENT; 761 + goto audit; 762 + } 763 + } else 764 + /* released below */ 765 + ns = aa_get_namespace(profile->ns); 766 + 767 + /* if the name was not specified, use the name of the current profile */ 768 + if (!hname) { 769 + if (unconfined(profile)) 770 + hname = ns->unconfined->base.hname; 771 + else 772 + hname = profile->base.hname; 773 + } 774 + 775 + perms = change_profile_perms(profile, ns, hname, request, 776 + profile->file.start); 777 + if (!(perms.allow & request)) { 778 + error = -EACCES; 779 + goto audit; 780 + } 781 + 782 + /* released below */ 783 + target = aa_lookup_profile(ns, hname); 784 + if (!target) { 785 + info = "profile not found"; 786 + error = -ENOENT; 787 + if (permtest || !COMPLAIN_MODE(profile)) 788 + goto audit; 789 + /* released below */ 790 + target = aa_new_null_profile(profile, 0); 791 + if (!target) { 792 + info = "failed null profile create"; 793 + error = -ENOMEM; 794 + goto audit; 795 + } 796 + } 797 + 798 + /* check if tracing task is allowed to trace target domain */ 799 + error = may_change_ptraced_domain(current, target); 800 + if (error) { 801 + info = "ptrace prevents transition"; 802 + goto audit; 803 + } 804 + 805 + if (permtest) 806 + goto audit; 807 + 808 + if (onexec) 809 + error = aa_set_current_onexec(target); 810 + else 811 + error = aa_replace_current_profile(target); 812 + 813 + audit: 814 + if (!permtest) 815 + error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request, 816 + name, hname, 0, info, error); 817 + 818 + aa_put_namespace(ns); 819 + aa_put_profile(target); 820 + put_cred(cred); 821 + 822 + return error; 823 + }
+457
security/apparmor/file.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor mediation of files 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #include "include/apparmor.h" 16 + #include "include/audit.h" 17 + #include "include/file.h" 18 + #include "include/match.h" 19 + #include "include/path.h" 20 + #include "include/policy.h" 21 + 22 + struct file_perms nullperms; 23 + 24 + 25 + /** 26 + * audit_file_mask - convert mask to permission string 27 + * @buffer: buffer to write string to (NOT NULL) 28 + * @mask: permission mask to convert 29 + */ 30 + static void audit_file_mask(struct audit_buffer *ab, u32 mask) 31 + { 32 + char str[10]; 33 + 34 + char *m = str; 35 + 36 + if (mask & AA_EXEC_MMAP) 37 + *m++ = 'm'; 38 + if (mask & (MAY_READ | AA_MAY_META_READ)) 39 + *m++ = 'r'; 40 + if (mask & (MAY_WRITE | AA_MAY_META_WRITE | AA_MAY_CHMOD | 41 + AA_MAY_CHOWN)) 42 + *m++ = 'w'; 43 + else if (mask & MAY_APPEND) 44 + *m++ = 'a'; 45 + if (mask & AA_MAY_CREATE) 46 + *m++ = 'c'; 47 + if (mask & AA_MAY_DELETE) 48 + *m++ = 'd'; 49 + if (mask & AA_MAY_LINK) 50 + *m++ = 'l'; 51 + if (mask & AA_MAY_LOCK) 52 + *m++ = 'k'; 53 + if (mask & MAY_EXEC) 54 + *m++ = 'x'; 55 + *m = '\0'; 56 + 57 + audit_log_string(ab, str); 58 + } 59 + 60 + /** 61 + * file_audit_cb - call back for file specific audit fields 62 + * @ab: audit_buffer (NOT NULL) 63 + * @va: audit struct to audit values of (NOT NULL) 64 + */ 65 + static void file_audit_cb(struct audit_buffer *ab, void *va) 66 + { 67 + struct common_audit_data *sa = va; 68 + uid_t fsuid = current_fsuid(); 69 + 70 + if (sa->aad.fs.request & AA_AUDIT_FILE_MASK) { 71 + audit_log_format(ab, " requested_mask="); 72 + audit_file_mask(ab, sa->aad.fs.request); 73 + } 74 + if (sa->aad.fs.denied & AA_AUDIT_FILE_MASK) { 75 + audit_log_format(ab, " denied_mask="); 76 + audit_file_mask(ab, sa->aad.fs.denied); 77 + } 78 + if (sa->aad.fs.request & AA_AUDIT_FILE_MASK) { 79 + audit_log_format(ab, " fsuid=%d", fsuid); 80 + audit_log_format(ab, " ouid=%d", sa->aad.fs.ouid); 81 + } 82 + 83 + if (sa->aad.fs.target) { 84 + audit_log_format(ab, " target="); 85 + audit_log_untrustedstring(ab, sa->aad.fs.target); 86 + } 87 + } 88 + 89 + /** 90 + * aa_audit_file - handle the auditing of file operations 91 + * @profile: the profile being enforced (NOT NULL) 92 + * @perms: the permissions computed for the request (NOT NULL) 93 + * @gfp: allocation flags 94 + * @op: operation being mediated 95 + * @request: permissions requested 96 + * @name: name of object being mediated (MAYBE NULL) 97 + * @target: name of target (MAYBE NULL) 98 + * @ouid: object uid 99 + * @info: extra information message (MAYBE NULL) 100 + * @error: 0 if operation allowed else failure error code 101 + * 102 + * Returns: %0 or error on failure 103 + */ 104 + int aa_audit_file(struct aa_profile *profile, struct file_perms *perms, 105 + gfp_t gfp, int op, u32 request, const char *name, 106 + const char *target, uid_t ouid, const char *info, int error) 107 + { 108 + int type = AUDIT_APPARMOR_AUTO; 109 + struct common_audit_data sa; 110 + COMMON_AUDIT_DATA_INIT(&sa, NONE); 111 + sa.aad.op = op, 112 + sa.aad.fs.request = request; 113 + sa.aad.name = name; 114 + sa.aad.fs.target = target; 115 + sa.aad.fs.ouid = ouid; 116 + sa.aad.info = info; 117 + sa.aad.error = error; 118 + 119 + if (likely(!sa.aad.error)) { 120 + u32 mask = perms->audit; 121 + 122 + if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL)) 123 + mask = 0xffff; 124 + 125 + /* mask off perms that are not being force audited */ 126 + sa.aad.fs.request &= mask; 127 + 128 + if (likely(!sa.aad.fs.request)) 129 + return 0; 130 + type = AUDIT_APPARMOR_AUDIT; 131 + } else { 132 + /* only report permissions that were denied */ 133 + sa.aad.fs.request = sa.aad.fs.request & ~perms->allow; 134 + 135 + if (sa.aad.fs.request & perms->kill) 136 + type = AUDIT_APPARMOR_KILL; 137 + 138 + /* quiet known rejects, assumes quiet and kill do not overlap */ 139 + if ((sa.aad.fs.request & perms->quiet) && 140 + AUDIT_MODE(profile) != AUDIT_NOQUIET && 141 + AUDIT_MODE(profile) != AUDIT_ALL) 142 + sa.aad.fs.request &= ~perms->quiet; 143 + 144 + if (!sa.aad.fs.request) 145 + return COMPLAIN_MODE(profile) ? 0 : sa.aad.error; 146 + } 147 + 148 + sa.aad.fs.denied = sa.aad.fs.request & ~perms->allow; 149 + return aa_audit(type, profile, gfp, &sa, file_audit_cb); 150 + } 151 + 152 + /** 153 + * map_old_perms - map old file perms layout to the new layout 154 + * @old: permission set in old mapping 155 + * 156 + * Returns: new permission mapping 157 + */ 158 + static u32 map_old_perms(u32 old) 159 + { 160 + u32 new = old & 0xf; 161 + if (old & MAY_READ) 162 + new |= AA_MAY_META_READ; 163 + if (old & MAY_WRITE) 164 + new |= AA_MAY_META_WRITE | AA_MAY_CREATE | AA_MAY_DELETE | 165 + AA_MAY_CHMOD | AA_MAY_CHOWN; 166 + if (old & 0x10) 167 + new |= AA_MAY_LINK; 168 + /* the old mapping lock and link_subset flags where overlaid 169 + * and use was determined by part of a pair that they were in 170 + */ 171 + if (old & 0x20) 172 + new |= AA_MAY_LOCK | AA_LINK_SUBSET; 173 + if (old & 0x40) /* AA_EXEC_MMAP */ 174 + new |= AA_EXEC_MMAP; 175 + 176 + new |= AA_MAY_META_READ; 177 + 178 + return new; 179 + } 180 + 181 + /** 182 + * compute_perms - convert dfa compressed perms to internal perms 183 + * @dfa: dfa to compute perms for (NOT NULL) 184 + * @state: state in dfa 185 + * @cond: conditions to consider (NOT NULL) 186 + * 187 + * TODO: convert from dfa + state to permission entry, do computation conversion 188 + * at load time. 189 + * 190 + * Returns: computed permission set 191 + */ 192 + static struct file_perms compute_perms(struct aa_dfa *dfa, unsigned int state, 193 + struct path_cond *cond) 194 + { 195 + struct file_perms perms; 196 + 197 + /* FIXME: change over to new dfa format 198 + * currently file perms are encoded in the dfa, new format 199 + * splits the permissions from the dfa. This mapping can be 200 + * done at profile load 201 + */ 202 + perms.kill = 0; 203 + 204 + if (current_fsuid() == cond->uid) { 205 + perms.allow = map_old_perms(dfa_user_allow(dfa, state)); 206 + perms.audit = map_old_perms(dfa_user_audit(dfa, state)); 207 + perms.quiet = map_old_perms(dfa_user_quiet(dfa, state)); 208 + perms.xindex = dfa_user_xindex(dfa, state); 209 + } else { 210 + perms.allow = map_old_perms(dfa_other_allow(dfa, state)); 211 + perms.audit = map_old_perms(dfa_other_audit(dfa, state)); 212 + perms.quiet = map_old_perms(dfa_other_quiet(dfa, state)); 213 + perms.xindex = dfa_other_xindex(dfa, state); 214 + } 215 + 216 + /* change_profile wasn't determined by ownership in old mapping */ 217 + if (ACCEPT_TABLE(dfa)[state] & 0x80000000) 218 + perms.allow |= AA_MAY_CHANGE_PROFILE; 219 + 220 + return perms; 221 + } 222 + 223 + /** 224 + * aa_str_perms - find permission that match @name 225 + * @dfa: to match against (MAYBE NULL) 226 + * @state: state to start matching in 227 + * @name: string to match against dfa (NOT NULL) 228 + * @cond: conditions to consider for permission set computation (NOT NULL) 229 + * @perms: Returns - the permissions found when matching @name 230 + * 231 + * Returns: the final state in @dfa when beginning @start and walking @name 232 + */ 233 + unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start, 234 + const char *name, struct path_cond *cond, 235 + struct file_perms *perms) 236 + { 237 + unsigned int state; 238 + if (!dfa) { 239 + *perms = nullperms; 240 + return DFA_NOMATCH; 241 + } 242 + 243 + state = aa_dfa_match(dfa, start, name); 244 + *perms = compute_perms(dfa, state, cond); 245 + 246 + return state; 247 + } 248 + 249 + /** 250 + * is_deleted - test if a file has been completely unlinked 251 + * @dentry: dentry of file to test for deletion (NOT NULL) 252 + * 253 + * Returns: %1 if deleted else %0 254 + */ 255 + static inline bool is_deleted(struct dentry *dentry) 256 + { 257 + if (d_unlinked(dentry) && dentry->d_inode->i_nlink == 0) 258 + return 1; 259 + return 0; 260 + } 261 + 262 + /** 263 + * aa_path_perm - do permissions check & audit for @path 264 + * @op: operation being checked 265 + * @profile: profile being enforced (NOT NULL) 266 + * @path: path to check permissions of (NOT NULL) 267 + * @flags: any additional path flags beyond what the profile specifies 268 + * @request: requested permissions 269 + * @cond: conditional info for this request (NOT NULL) 270 + * 271 + * Returns: %0 else error if access denied or other error 272 + */ 273 + int aa_path_perm(int op, struct aa_profile *profile, struct path *path, 274 + int flags, u32 request, struct path_cond *cond) 275 + { 276 + char *buffer = NULL; 277 + struct file_perms perms = {}; 278 + const char *name, *info = NULL; 279 + int error; 280 + 281 + flags |= profile->path_flags | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0); 282 + error = aa_get_name(path, flags, &buffer, &name); 283 + if (error) { 284 + if (error == -ENOENT && is_deleted(path->dentry)) { 285 + /* Access to open files that are deleted are 286 + * give a pass (implicit delegation) 287 + */ 288 + error = 0; 289 + perms.allow = request; 290 + } else if (error == -ENOENT) 291 + info = "Failed name lookup - deleted entry"; 292 + else if (error == -ESTALE) 293 + info = "Failed name lookup - disconnected path"; 294 + else if (error == -ENAMETOOLONG) 295 + info = "Failed name lookup - name too long"; 296 + else 297 + info = "Failed name lookup"; 298 + } else { 299 + aa_str_perms(profile->file.dfa, profile->file.start, name, cond, 300 + &perms); 301 + if (request & ~perms.allow) 302 + error = -EACCES; 303 + } 304 + error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request, name, 305 + NULL, cond->uid, info, error); 306 + kfree(buffer); 307 + 308 + return error; 309 + } 310 + 311 + /** 312 + * xindex_is_subset - helper for aa_path_link 313 + * @link: link permission set 314 + * @target: target permission set 315 + * 316 + * test target x permissions are equal OR a subset of link x permissions 317 + * this is done as part of the subset test, where a hardlink must have 318 + * a subset of permissions that the target has. 319 + * 320 + * Returns: %1 if subset else %0 321 + */ 322 + static inline bool xindex_is_subset(u32 link, u32 target) 323 + { 324 + if (((link & ~AA_X_UNSAFE) != (target & ~AA_X_UNSAFE)) || 325 + ((link & AA_X_UNSAFE) && !(target & AA_X_UNSAFE))) 326 + return 0; 327 + 328 + return 1; 329 + } 330 + 331 + /** 332 + * aa_path_link - Handle hard link permission check 333 + * @profile: the profile being enforced (NOT NULL) 334 + * @old_dentry: the target dentry (NOT NULL) 335 + * @new_dir: directory the new link will be created in (NOT NULL) 336 + * @new_dentry: the link being created (NOT NULL) 337 + * 338 + * Handle the permission test for a link & target pair. Permission 339 + * is encoded as a pair where the link permission is determined 340 + * first, and if allowed, the target is tested. The target test 341 + * is done from the point of the link match (not start of DFA) 342 + * making the target permission dependent on the link permission match. 343 + * 344 + * The subset test if required forces that permissions granted 345 + * on link are a subset of the permission granted to target. 346 + * 347 + * Returns: %0 if allowed else error 348 + */ 349 + int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, 350 + struct path *new_dir, struct dentry *new_dentry) 351 + { 352 + struct path link = { new_dir->mnt, new_dentry }; 353 + struct path target = { new_dir->mnt, old_dentry }; 354 + struct path_cond cond = { 355 + old_dentry->d_inode->i_uid, 356 + old_dentry->d_inode->i_mode 357 + }; 358 + char *buffer = NULL, *buffer2 = NULL; 359 + const char *lname, *tname = NULL, *info = NULL; 360 + struct file_perms lperms, perms; 361 + u32 request = AA_MAY_LINK; 362 + unsigned int state; 363 + int error; 364 + 365 + lperms = nullperms; 366 + 367 + /* buffer freed below, lname is pointer in buffer */ 368 + error = aa_get_name(&link, profile->path_flags, &buffer, &lname); 369 + if (error) 370 + goto audit; 371 + 372 + /* buffer2 freed below, tname is pointer in buffer2 */ 373 + error = aa_get_name(&target, profile->path_flags, &buffer2, &tname); 374 + if (error) 375 + goto audit; 376 + 377 + error = -EACCES; 378 + /* aa_str_perms - handles the case of the dfa being NULL */ 379 + state = aa_str_perms(profile->file.dfa, profile->file.start, lname, 380 + &cond, &lperms); 381 + 382 + if (!(lperms.allow & AA_MAY_LINK)) 383 + goto audit; 384 + 385 + /* test to see if target can be paired with link */ 386 + state = aa_dfa_null_transition(profile->file.dfa, state); 387 + aa_str_perms(profile->file.dfa, state, tname, &cond, &perms); 388 + 389 + /* force audit/quiet masks for link are stored in the second entry 390 + * in the link pair. 391 + */ 392 + lperms.audit = perms.audit; 393 + lperms.quiet = perms.quiet; 394 + lperms.kill = perms.kill; 395 + 396 + if (!(perms.allow & AA_MAY_LINK)) { 397 + info = "target restricted"; 398 + goto audit; 399 + } 400 + 401 + /* done if link subset test is not required */ 402 + if (!(perms.allow & AA_LINK_SUBSET)) 403 + goto done_tests; 404 + 405 + /* Do link perm subset test requiring allowed permission on link are a 406 + * subset of the allowed permissions on target. 407 + */ 408 + aa_str_perms(profile->file.dfa, profile->file.start, tname, &cond, 409 + &perms); 410 + 411 + /* AA_MAY_LINK is not considered in the subset test */ 412 + request = lperms.allow & ~AA_MAY_LINK; 413 + lperms.allow &= perms.allow | AA_MAY_LINK; 414 + 415 + request |= AA_AUDIT_FILE_MASK & (lperms.allow & ~perms.allow); 416 + if (request & ~lperms.allow) { 417 + goto audit; 418 + } else if ((lperms.allow & MAY_EXEC) && 419 + !xindex_is_subset(lperms.xindex, perms.xindex)) { 420 + lperms.allow &= ~MAY_EXEC; 421 + request |= MAY_EXEC; 422 + info = "link not subset of target"; 423 + goto audit; 424 + } 425 + 426 + done_tests: 427 + error = 0; 428 + 429 + audit: 430 + error = aa_audit_file(profile, &lperms, GFP_KERNEL, OP_LINK, request, 431 + lname, tname, cond.uid, info, error); 432 + kfree(buffer); 433 + kfree(buffer2); 434 + 435 + return error; 436 + } 437 + 438 + /** 439 + * aa_file_perm - do permission revalidation check & audit for @file 440 + * @op: operation being checked 441 + * @profile: profile being enforced (NOT NULL) 442 + * @file: file to revalidate access permissions on (NOT NULL) 443 + * @request: requested permissions 444 + * 445 + * Returns: %0 if access allowed else error 446 + */ 447 + int aa_file_perm(int op, struct aa_profile *profile, struct file *file, 448 + u32 request) 449 + { 450 + struct path_cond cond = { 451 + .uid = file->f_path.dentry->d_inode->i_uid, 452 + .mode = file->f_path.dentry->d_inode->i_mode 453 + }; 454 + 455 + return aa_path_perm(op, profile, &file->f_path, PATH_DELEGATE_DELETED, 456 + request, &cond); 457 + }
+92
security/apparmor/include/apparmor.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor basic global and lib definitions 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #ifndef __APPARMOR_H 16 + #define __APPARMOR_H 17 + 18 + #include <linux/fs.h> 19 + 20 + #include "match.h" 21 + 22 + /* Control parameters settable through module/boot flags */ 23 + extern enum audit_mode aa_g_audit; 24 + extern int aa_g_audit_header; 25 + extern int aa_g_debug; 26 + extern int aa_g_lock_policy; 27 + extern int aa_g_logsyscall; 28 + extern int aa_g_paranoid_load; 29 + extern unsigned int aa_g_path_max; 30 + 31 + /* 32 + * DEBUG remains global (no per profile flag) since it is mostly used in sysctl 33 + * which is not related to profile accesses. 34 + */ 35 + 36 + #define AA_DEBUG(fmt, args...) \ 37 + do { \ 38 + if (aa_g_debug && printk_ratelimit()) \ 39 + printk(KERN_DEBUG "AppArmor: " fmt, ##args); \ 40 + } while (0) 41 + 42 + #define AA_ERROR(fmt, args...) \ 43 + do { \ 44 + if (printk_ratelimit()) \ 45 + printk(KERN_ERR "AppArmor: " fmt, ##args); \ 46 + } while (0) 47 + 48 + /* Flag indicating whether initialization completed */ 49 + extern int apparmor_initialized __initdata; 50 + 51 + /* fn's in lib */ 52 + char *aa_split_fqname(char *args, char **ns_name); 53 + void aa_info_message(const char *str); 54 + void *kvmalloc(size_t size); 55 + void kvfree(void *buffer); 56 + 57 + 58 + /** 59 + * aa_strneq - compare null terminated @str to a non null terminated substring 60 + * @str: a null terminated string 61 + * @sub: a substring, not necessarily null terminated 62 + * @len: length of @sub to compare 63 + * 64 + * The @str string must be full consumed for this to be considered a match 65 + */ 66 + static inline bool aa_strneq(const char *str, const char *sub, int len) 67 + { 68 + return !strncmp(str, sub, len) && !str[len]; 69 + } 70 + 71 + /** 72 + * aa_dfa_null_transition - step to next state after null character 73 + * @dfa: the dfa to match against 74 + * @start: the state of the dfa to start matching in 75 + * 76 + * aa_dfa_null_transition transitions to the next state after a null 77 + * character which is not used in standard matching and is only 78 + * used to separate pairs. 79 + */ 80 + static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, 81 + unsigned int start) 82 + { 83 + /* the null transition only needs the string's null terminator byte */ 84 + return aa_dfa_match_len(dfa, start, "", 1); 85 + } 86 + 87 + static inline bool mediated_filesystem(struct inode *inode) 88 + { 89 + return !(inode->i_sb->s_flags & MS_NOUSER); 90 + } 91 + 92 + #endif /* __APPARMOR_H */
+20
security/apparmor/include/apparmorfs.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor filesystem definitions. 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #ifndef __AA_APPARMORFS_H 16 + #define __AA_APPARMORFS_H 17 + 18 + extern void __init aa_destroy_aafs(void); 19 + 20 + #endif /* __AA_APPARMORFS_H */
+123
security/apparmor/include/audit.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor auditing function definitions. 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #ifndef __AA_AUDIT_H 16 + #define __AA_AUDIT_H 17 + 18 + #include <linux/audit.h> 19 + #include <linux/fs.h> 20 + #include <linux/lsm_audit.h> 21 + #include <linux/sched.h> 22 + #include <linux/slab.h> 23 + 24 + #include "file.h" 25 + 26 + struct aa_profile; 27 + 28 + extern const char *audit_mode_names[]; 29 + #define AUDIT_MAX_INDEX 5 30 + 31 + #define AUDIT_APPARMOR_AUTO 0 /* auto choose audit message type */ 32 + 33 + enum audit_mode { 34 + AUDIT_NORMAL, /* follow normal auditing of accesses */ 35 + AUDIT_QUIET_DENIED, /* quiet all denied access messages */ 36 + AUDIT_QUIET, /* quiet all messages */ 37 + AUDIT_NOQUIET, /* do not quiet audit messages */ 38 + AUDIT_ALL /* audit all accesses */ 39 + }; 40 + 41 + enum audit_type { 42 + AUDIT_APPARMOR_AUDIT, 43 + AUDIT_APPARMOR_ALLOWED, 44 + AUDIT_APPARMOR_DENIED, 45 + AUDIT_APPARMOR_HINT, 46 + AUDIT_APPARMOR_STATUS, 47 + AUDIT_APPARMOR_ERROR, 48 + AUDIT_APPARMOR_KILL 49 + }; 50 + 51 + extern const char *op_table[]; 52 + enum aa_ops { 53 + OP_NULL, 54 + 55 + OP_SYSCTL, 56 + OP_CAPABLE, 57 + 58 + OP_UNLINK, 59 + OP_MKDIR, 60 + OP_RMDIR, 61 + OP_MKNOD, 62 + OP_TRUNC, 63 + OP_LINK, 64 + OP_SYMLINK, 65 + OP_RENAME_SRC, 66 + OP_RENAME_DEST, 67 + OP_CHMOD, 68 + OP_CHOWN, 69 + OP_GETATTR, 70 + OP_OPEN, 71 + 72 + OP_FPERM, 73 + OP_FLOCK, 74 + OP_FMMAP, 75 + OP_FMPROT, 76 + 77 + OP_CREATE, 78 + OP_POST_CREATE, 79 + OP_BIND, 80 + OP_CONNECT, 81 + OP_LISTEN, 82 + OP_ACCEPT, 83 + OP_SENDMSG, 84 + OP_RECVMSG, 85 + OP_GETSOCKNAME, 86 + OP_GETPEERNAME, 87 + OP_GETSOCKOPT, 88 + OP_SETSOCKOPT, 89 + OP_SOCK_SHUTDOWN, 90 + 91 + OP_PTRACE, 92 + 93 + OP_EXEC, 94 + OP_CHANGE_HAT, 95 + OP_CHANGE_PROFILE, 96 + OP_CHANGE_ONEXEC, 97 + 98 + OP_SETPROCATTR, 99 + OP_SETRLIMIT, 100 + 101 + OP_PROF_REPL, 102 + OP_PROF_LOAD, 103 + OP_PROF_RM, 104 + }; 105 + 106 + 107 + /* define a short hand for apparmor_audit_data portion of common_audit_data */ 108 + #define aad apparmor_audit_data 109 + 110 + void aa_audit_msg(int type, struct common_audit_data *sa, 111 + void (*cb) (struct audit_buffer *, void *)); 112 + int aa_audit(int type, struct aa_profile *profile, gfp_t gfp, 113 + struct common_audit_data *sa, 114 + void (*cb) (struct audit_buffer *, void *)); 115 + 116 + static inline int complain_error(int error) 117 + { 118 + if (error == -EPERM || error == -EACCES) 119 + return 0; 120 + return error; 121 + } 122 + 123 + #endif /* __AA_AUDIT_H */
+45
security/apparmor/include/capability.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor capability mediation definitions. 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #ifndef __AA_CAPABILITY_H 16 + #define __AA_CAPABILITY_H 17 + 18 + #include <linux/sched.h> 19 + 20 + struct aa_profile; 21 + 22 + /* aa_caps - confinement data for capabilities 23 + * @allowed: capabilities mask 24 + * @audit: caps that are to be audited 25 + * @quiet: caps that should not be audited 26 + * @kill: caps that when requested will result in the task being killed 27 + * @extended: caps that are subject finer grained mediation 28 + */ 29 + struct aa_caps { 30 + kernel_cap_t allow; 31 + kernel_cap_t audit; 32 + kernel_cap_t quiet; 33 + kernel_cap_t kill; 34 + kernel_cap_t extended; 35 + }; 36 + 37 + int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap, 38 + int audit); 39 + 40 + static inline void aa_free_cap_rules(struct aa_caps *caps) 41 + { 42 + /* NOP */ 43 + } 44 + 45 + #endif /* __AA_CAPBILITY_H */
+154
security/apparmor/include/context.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor contexts used to associate "labels" to objects. 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #ifndef __AA_CONTEXT_H 16 + #define __AA_CONTEXT_H 17 + 18 + #include <linux/cred.h> 19 + #include <linux/slab.h> 20 + #include <linux/sched.h> 21 + 22 + #include "policy.h" 23 + 24 + /* struct aa_file_cxt - the AppArmor context the file was opened in 25 + * @perms: the permission the file was opened with 26 + * 27 + * The file_cxt could currently be directly stored in file->f_security 28 + * as the profile reference is now stored in the f_cred. However the 29 + * cxt struct will expand in the future so we keep the struct. 30 + */ 31 + struct aa_file_cxt { 32 + u16 allow; 33 + }; 34 + 35 + /** 36 + * aa_alloc_file_context - allocate file_cxt 37 + * @gfp: gfp flags for allocation 38 + * 39 + * Returns: file_cxt or NULL on failure 40 + */ 41 + static inline struct aa_file_cxt *aa_alloc_file_context(gfp_t gfp) 42 + { 43 + return kzalloc(sizeof(struct aa_file_cxt), gfp); 44 + } 45 + 46 + /** 47 + * aa_free_file_context - free a file_cxt 48 + * @cxt: file_cxt to free (MAYBE_NULL) 49 + */ 50 + static inline void aa_free_file_context(struct aa_file_cxt *cxt) 51 + { 52 + if (cxt) 53 + kzfree(cxt); 54 + } 55 + 56 + /** 57 + * struct aa_task_cxt - primary label for confined tasks 58 + * @profile: the current profile (NOT NULL) 59 + * @exec: profile to transition to on next exec (MAYBE NULL) 60 + * @previous: profile the task may return to (MAYBE NULL) 61 + * @token: magic value the task must know for returning to @previous_profile 62 + * 63 + * Contains the task's current profile (which could change due to 64 + * change_hat). Plus the hat_magic needed during change_hat. 65 + * 66 + * TODO: make so a task can be confined by a stack of contexts 67 + */ 68 + struct aa_task_cxt { 69 + struct aa_profile *profile; 70 + struct aa_profile *onexec; 71 + struct aa_profile *previous; 72 + u64 token; 73 + }; 74 + 75 + struct aa_task_cxt *aa_alloc_task_context(gfp_t flags); 76 + void aa_free_task_context(struct aa_task_cxt *cxt); 77 + void aa_dup_task_context(struct aa_task_cxt *new, 78 + const struct aa_task_cxt *old); 79 + int aa_replace_current_profile(struct aa_profile *profile); 80 + int aa_set_current_onexec(struct aa_profile *profile); 81 + int aa_set_current_hat(struct aa_profile *profile, u64 token); 82 + int aa_restore_previous_profile(u64 cookie); 83 + 84 + /** 85 + * __aa_task_is_confined - determine if @task has any confinement 86 + * @task: task to check confinement of (NOT NULL) 87 + * 88 + * If @task != current needs to be called in RCU safe critical section 89 + */ 90 + static inline bool __aa_task_is_confined(struct task_struct *task) 91 + { 92 + struct aa_task_cxt *cxt = __task_cred(task)->security; 93 + 94 + BUG_ON(!cxt || !cxt->profile); 95 + if (unconfined(aa_newest_version(cxt->profile))) 96 + return 0; 97 + 98 + return 1; 99 + } 100 + 101 + /** 102 + * aa_cred_profile - obtain cred's profiles 103 + * @cred: cred to obtain profiles from (NOT NULL) 104 + * 105 + * Returns: confining profile 106 + * 107 + * does NOT increment reference count 108 + */ 109 + static inline struct aa_profile *aa_cred_profile(const struct cred *cred) 110 + { 111 + struct aa_task_cxt *cxt = cred->security; 112 + BUG_ON(!cxt || !cxt->profile); 113 + return aa_newest_version(cxt->profile); 114 + } 115 + 116 + /** 117 + * __aa_current_profile - find the current tasks confining profile 118 + * 119 + * Returns: up to date confining profile or the ns unconfined profile (NOT NULL) 120 + * 121 + * This fn will not update the tasks cred to the most up to date version 122 + * of the profile so it is safe to call when inside of locks. 123 + */ 124 + static inline struct aa_profile *__aa_current_profile(void) 125 + { 126 + return aa_cred_profile(current_cred()); 127 + } 128 + 129 + /** 130 + * aa_current_profile - find the current tasks confining profile and do updates 131 + * 132 + * Returns: up to date confining profile or the ns unconfined profile (NOT NULL) 133 + * 134 + * This fn will update the tasks cred structure if the profile has been 135 + * replaced. Not safe to call inside locks 136 + */ 137 + static inline struct aa_profile *aa_current_profile(void) 138 + { 139 + const struct aa_task_cxt *cxt = current_cred()->security; 140 + struct aa_profile *profile; 141 + BUG_ON(!cxt || !cxt->profile); 142 + 143 + profile = aa_newest_version(cxt->profile); 144 + /* 145 + * Whether or not replacement succeeds, use newest profile so 146 + * there is no need to update it after replacement. 147 + */ 148 + if (unlikely((cxt->profile != profile))) 149 + aa_replace_current_profile(profile); 150 + 151 + return profile; 152 + } 153 + 154 + #endif /* __AA_CONTEXT_H */
+36
security/apparmor/include/domain.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor security domain transition function definitions. 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #include <linux/binfmts.h> 16 + #include <linux/types.h> 17 + 18 + #ifndef __AA_DOMAIN_H 19 + #define __AA_DOMAIN_H 20 + 21 + struct aa_domain { 22 + int size; 23 + char **table; 24 + }; 25 + 26 + int apparmor_bprm_set_creds(struct linux_binprm *bprm); 27 + int apparmor_bprm_secureexec(struct linux_binprm *bprm); 28 + void apparmor_bprm_committing_creds(struct linux_binprm *bprm); 29 + void apparmor_bprm_committed_creds(struct linux_binprm *bprm); 30 + 31 + void aa_free_domain_entries(struct aa_domain *domain); 32 + int aa_change_hat(const char *hats[], int count, u64 token, bool permtest); 33 + int aa_change_profile(const char *ns_name, const char *name, bool onexec, 34 + bool permtest); 35 + 36 + #endif /* __AA_DOMAIN_H */
+217
security/apparmor/include/file.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor file mediation function definitions. 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #ifndef __AA_FILE_H 16 + #define __AA_FILE_H 17 + 18 + #include <linux/path.h> 19 + 20 + #include "domain.h" 21 + #include "match.h" 22 + 23 + struct aa_profile; 24 + 25 + /* 26 + * We use MAY_EXEC, MAY_WRITE, MAY_READ, MAY_APPEND and the following flags 27 + * for profile permissions 28 + */ 29 + #define AA_MAY_CREATE 0x0010 30 + #define AA_MAY_DELETE 0x0020 31 + #define AA_MAY_META_WRITE 0x0040 32 + #define AA_MAY_META_READ 0x0080 33 + 34 + #define AA_MAY_CHMOD 0x0100 35 + #define AA_MAY_CHOWN 0x0200 36 + #define AA_MAY_LOCK 0x0400 37 + #define AA_EXEC_MMAP 0x0800 38 + 39 + #define AA_MAY_LINK 0x1000 40 + #define AA_LINK_SUBSET AA_MAY_LOCK /* overlaid */ 41 + #define AA_MAY_ONEXEC 0x40000000 /* exec allows onexec */ 42 + #define AA_MAY_CHANGE_PROFILE 0x80000000 43 + #define AA_MAY_CHANGEHAT 0x80000000 /* ctrl auditing only */ 44 + 45 + #define AA_AUDIT_FILE_MASK (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND |\ 46 + AA_MAY_CREATE | AA_MAY_DELETE | \ 47 + AA_MAY_META_READ | AA_MAY_META_WRITE | \ 48 + AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_LOCK | \ 49 + AA_EXEC_MMAP | AA_MAY_LINK) 50 + 51 + /* 52 + * The xindex is broken into 3 parts 53 + * - index - an index into either the exec name table or the variable table 54 + * - exec type - which determines how the executable name and index are used 55 + * - flags - which modify how the destination name is applied 56 + */ 57 + #define AA_X_INDEX_MASK 0x03ff 58 + 59 + #define AA_X_TYPE_MASK 0x0c00 60 + #define AA_X_TYPE_SHIFT 10 61 + #define AA_X_NONE 0x0000 62 + #define AA_X_NAME 0x0400 /* use executable name px */ 63 + #define AA_X_TABLE 0x0800 /* use a specified name ->n# */ 64 + 65 + #define AA_X_UNSAFE 0x1000 66 + #define AA_X_CHILD 0x2000 /* make >AA_X_NONE apply to children */ 67 + #define AA_X_INHERIT 0x4000 68 + #define AA_X_UNCONFINED 0x8000 69 + 70 + /* AA_SECURE_X_NEEDED - is passed in the bprm->unsafe field */ 71 + #define AA_SECURE_X_NEEDED 0x8000 72 + 73 + /* need to make conditional which ones are being set */ 74 + struct path_cond { 75 + uid_t uid; 76 + umode_t mode; 77 + }; 78 + 79 + /* struct file_perms - file permission 80 + * @allow: mask of permissions that are allowed 81 + * @audit: mask of permissions to force an audit message for 82 + * @quiet: mask of permissions to quiet audit messages for 83 + * @kill: mask of permissions that when matched will kill the task 84 + * @xindex: exec transition index if @allow contains MAY_EXEC 85 + * 86 + * The @audit and @queit mask should be mutually exclusive. 87 + */ 88 + struct file_perms { 89 + u32 allow; 90 + u32 audit; 91 + u32 quiet; 92 + u32 kill; 93 + u16 xindex; 94 + }; 95 + 96 + extern struct file_perms nullperms; 97 + 98 + #define COMBINED_PERM_MASK(X) ((X).allow | (X).audit | (X).quiet | (X).kill) 99 + 100 + /* FIXME: split perms from dfa and match this to description 101 + * also add delegation info. 102 + */ 103 + static inline u16 dfa_map_xindex(u16 mask) 104 + { 105 + u16 old_index = (mask >> 10) & 0xf; 106 + u16 index = 0; 107 + 108 + if (mask & 0x100) 109 + index |= AA_X_UNSAFE; 110 + if (mask & 0x200) 111 + index |= AA_X_INHERIT; 112 + if (mask & 0x80) 113 + index |= AA_X_UNCONFINED; 114 + 115 + if (old_index == 1) { 116 + index |= AA_X_UNCONFINED; 117 + } else if (old_index == 2) { 118 + index |= AA_X_NAME; 119 + } else if (old_index == 3) { 120 + index |= AA_X_NAME | AA_X_CHILD; 121 + } else { 122 + index |= AA_X_TABLE; 123 + index |= old_index - 4; 124 + } 125 + 126 + return index; 127 + } 128 + 129 + /* 130 + * map old dfa inline permissions to new format 131 + */ 132 + #define dfa_user_allow(dfa, state) (((ACCEPT_TABLE(dfa)[state]) & 0x7f) | \ 133 + ((ACCEPT_TABLE(dfa)[state]) & 0x80000000)) 134 + #define dfa_user_audit(dfa, state) ((ACCEPT_TABLE2(dfa)[state]) & 0x7f) 135 + #define dfa_user_quiet(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 7) & 0x7f) 136 + #define dfa_user_xindex(dfa, state) \ 137 + (dfa_map_xindex(ACCEPT_TABLE(dfa)[state] & 0x3fff)) 138 + 139 + #define dfa_other_allow(dfa, state) ((((ACCEPT_TABLE(dfa)[state]) >> 14) & \ 140 + 0x7f) | \ 141 + ((ACCEPT_TABLE(dfa)[state]) & 0x80000000)) 142 + #define dfa_other_audit(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 14) & 0x7f) 143 + #define dfa_other_quiet(dfa, state) \ 144 + ((((ACCEPT_TABLE2(dfa)[state]) >> 7) >> 14) & 0x7f) 145 + #define dfa_other_xindex(dfa, state) \ 146 + dfa_map_xindex((ACCEPT_TABLE(dfa)[state] >> 14) & 0x3fff) 147 + 148 + int aa_audit_file(struct aa_profile *profile, struct file_perms *perms, 149 + gfp_t gfp, int op, u32 request, const char *name, 150 + const char *target, uid_t ouid, const char *info, int error); 151 + 152 + /** 153 + * struct aa_file_rules - components used for file rule permissions 154 + * @dfa: dfa to match path names and conditionals against 155 + * @perms: permission table indexed by the matched state accept entry of @dfa 156 + * @trans: transition table for indexed by named x transitions 157 + * 158 + * File permission are determined by matching a path against @dfa and then 159 + * then using the value of the accept entry for the matching state as 160 + * an index into @perms. If a named exec transition is required it is 161 + * looked up in the transition table. 162 + */ 163 + struct aa_file_rules { 164 + unsigned int start; 165 + struct aa_dfa *dfa; 166 + /* struct perms perms; */ 167 + struct aa_domain trans; 168 + /* TODO: add delegate table */ 169 + }; 170 + 171 + unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start, 172 + const char *name, struct path_cond *cond, 173 + struct file_perms *perms); 174 + 175 + int aa_path_perm(int op, struct aa_profile *profile, struct path *path, 176 + int flags, u32 request, struct path_cond *cond); 177 + 178 + int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, 179 + struct path *new_dir, struct dentry *new_dentry); 180 + 181 + int aa_file_perm(int op, struct aa_profile *profile, struct file *file, 182 + u32 request); 183 + 184 + static inline void aa_free_file_rules(struct aa_file_rules *rules) 185 + { 186 + aa_put_dfa(rules->dfa); 187 + aa_free_domain_entries(&rules->trans); 188 + } 189 + 190 + #define ACC_FMODE(x) (("\000\004\002\006"[(x)&O_ACCMODE]) | (((x) << 1) & 0x40)) 191 + 192 + /* from namei.c */ 193 + #define MAP_OPEN_FLAGS(x) ((((x) + 1) & O_ACCMODE) ? (x) + 1 : (x)) 194 + 195 + /** 196 + * aa_map_file_perms - map file flags to AppArmor permissions 197 + * @file: open file to map flags to AppArmor permissions 198 + * 199 + * Returns: apparmor permission set for the file 200 + */ 201 + static inline u32 aa_map_file_to_perms(struct file *file) 202 + { 203 + int flags = MAP_OPEN_FLAGS(file->f_flags); 204 + u32 perms = ACC_FMODE(file->f_mode); 205 + 206 + if ((flags & O_APPEND) && (perms & MAY_WRITE)) 207 + perms = (perms & ~MAY_WRITE) | MAY_APPEND; 208 + /* trunc implies write permission */ 209 + if (flags & O_TRUNC) 210 + perms |= MAY_WRITE; 211 + if (flags & O_CREAT) 212 + perms |= AA_MAY_CREATE; 213 + 214 + return perms; 215 + } 216 + 217 + #endif /* __AA_FILE_H */
+28
security/apparmor/include/ipc.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor ipc mediation function definitions. 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #ifndef __AA_IPC_H 16 + #define __AA_IPC_H 17 + 18 + #include <linux/sched.h> 19 + 20 + struct aa_profile; 21 + 22 + int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer, 23 + struct aa_profile *tracee, unsigned int mode); 24 + 25 + int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee, 26 + unsigned int mode); 27 + 28 + #endif /* __AA_IPC_H */
+132
security/apparmor/include/match.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor policy dfa matching engine definitions. 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #ifndef __AA_MATCH_H 16 + #define __AA_MATCH_H 17 + 18 + #include <linux/workqueue.h> 19 + 20 + #define DFA_NOMATCH 0 21 + #define DFA_START 1 22 + 23 + #define DFA_VALID_PERM_MASK 0xffffffff 24 + #define DFA_VALID_PERM2_MASK 0xffffffff 25 + 26 + /** 27 + * The format used for transition tables is based on the GNU flex table 28 + * file format (--tables-file option; see Table File Format in the flex 29 + * info pages and the flex sources for documentation). The magic number 30 + * used in the header is 0x1B5E783D insted of 0xF13C57B1 though, because 31 + * the YY_ID_CHK (check) and YY_ID_DEF (default) tables are used 32 + * slightly differently (see the apparmor-parser package). 33 + */ 34 + 35 + #define YYTH_MAGIC 0x1B5E783D 36 + #define YYTH_DEF_RECURSE 0x1 /* DEF Table is recursive */ 37 + 38 + struct table_set_header { 39 + u32 th_magic; /* YYTH_MAGIC */ 40 + u32 th_hsize; 41 + u32 th_ssize; 42 + u16 th_flags; 43 + char th_version[]; 44 + }; 45 + 46 + /* The YYTD_ID are one less than flex table mappings. The flex id 47 + * has 1 subtracted at table load time, this allows us to directly use the 48 + * ID's as indexes. 49 + */ 50 + #define YYTD_ID_ACCEPT 0 51 + #define YYTD_ID_BASE 1 52 + #define YYTD_ID_CHK 2 53 + #define YYTD_ID_DEF 3 54 + #define YYTD_ID_EC 4 55 + #define YYTD_ID_META 5 56 + #define YYTD_ID_ACCEPT2 6 57 + #define YYTD_ID_NXT 7 58 + #define YYTD_ID_TSIZE 8 59 + 60 + #define YYTD_DATA8 1 61 + #define YYTD_DATA16 2 62 + #define YYTD_DATA32 4 63 + #define YYTD_DATA64 8 64 + 65 + /* Each ACCEPT2 table gets 6 dedicated flags, YYTD_DATAX define the 66 + * first flags 67 + */ 68 + #define ACCEPT1_FLAGS(X) ((X) & 0x3f) 69 + #define ACCEPT2_FLAGS(X) ACCEPT1_FLAGS((X) >> YYTD_ID_ACCEPT2) 70 + #define TO_ACCEPT1_FLAG(X) ACCEPT1_FLAGS(X) 71 + #define TO_ACCEPT2_FLAG(X) (ACCEPT1_FLAGS(X) << YYTD_ID_ACCEPT2) 72 + #define DFA_FLAG_VERIFY_STATES 0x1000 73 + 74 + struct table_header { 75 + u16 td_id; 76 + u16 td_flags; 77 + u32 td_hilen; 78 + u32 td_lolen; 79 + char td_data[]; 80 + }; 81 + 82 + #define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF]->td_data)) 83 + #define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE]->td_data)) 84 + #define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT]->td_data)) 85 + #define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK]->td_data)) 86 + #define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC]->td_data)) 87 + #define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT]->td_data)) 88 + #define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2]->td_data)) 89 + 90 + struct aa_dfa { 91 + struct kref count; 92 + u16 flags; 93 + struct table_header *tables[YYTD_ID_TSIZE]; 94 + }; 95 + 96 + #define byte_to_byte(X) (X) 97 + 98 + #define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \ 99 + do { \ 100 + typeof(LEN) __i; \ 101 + TYPE *__t = (TYPE *) TABLE; \ 102 + TYPE *__b = (TYPE *) BLOB; \ 103 + for (__i = 0; __i < LEN; __i++) { \ 104 + __t[__i] = NTOHX(__b[__i]); \ 105 + } \ 106 + } while (0) 107 + 108 + static inline size_t table_size(size_t len, size_t el_size) 109 + { 110 + return ALIGN(sizeof(struct table_header) + len * el_size, 8); 111 + } 112 + 113 + struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags); 114 + unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start, 115 + const char *str, int len); 116 + unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start, 117 + const char *str); 118 + void aa_dfa_free_kref(struct kref *kref); 119 + 120 + /** 121 + * aa_put_dfa - put a dfa refcount 122 + * @dfa: dfa to put refcount (MAYBE NULL) 123 + * 124 + * Requires: if @dfa != NULL that a valid refcount be held 125 + */ 126 + static inline void aa_put_dfa(struct aa_dfa *dfa) 127 + { 128 + if (dfa) 129 + kref_put(&dfa->count, aa_dfa_free_kref); 130 + } 131 + 132 + #endif /* __AA_MATCH_H */
+31
security/apparmor/include/path.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor basic path manipulation function definitions. 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #ifndef __AA_PATH_H 16 + #define __AA_PATH_H 17 + 18 + 19 + enum path_flags { 20 + PATH_IS_DIR = 0x1, /* path is a directory */ 21 + PATH_CONNECT_PATH = 0x4, /* connect disconnected paths to / */ 22 + PATH_CHROOT_REL = 0x8, /* do path lookup relative to chroot */ 23 + PATH_CHROOT_NSCONNECT = 0x10, /* connect paths that are at ns root */ 24 + 25 + PATH_DELEGATE_DELETED = 0x08000, /* delegate deleted files */ 26 + PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */ 27 + }; 28 + 29 + int aa_get_name(struct path *path, int flags, char **buffer, const char **name); 30 + 31 + #endif /* __AA_PATH_H */
+305
security/apparmor/include/policy.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor policy definitions. 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #ifndef __AA_POLICY_H 16 + #define __AA_POLICY_H 17 + 18 + #include <linux/capability.h> 19 + #include <linux/cred.h> 20 + #include <linux/kref.h> 21 + #include <linux/sched.h> 22 + #include <linux/slab.h> 23 + #include <linux/socket.h> 24 + 25 + #include "apparmor.h" 26 + #include "audit.h" 27 + #include "capability.h" 28 + #include "domain.h" 29 + #include "file.h" 30 + #include "resource.h" 31 + 32 + extern const char *profile_mode_names[]; 33 + #define APPARMOR_NAMES_MAX_INDEX 3 34 + 35 + #define COMPLAIN_MODE(_profile) \ 36 + ((aa_g_profile_mode == APPARMOR_COMPLAIN) || \ 37 + ((_profile)->mode == APPARMOR_COMPLAIN)) 38 + 39 + #define KILL_MODE(_profile) \ 40 + ((aa_g_profile_mode == APPARMOR_KILL) || \ 41 + ((_profile)->mode == APPARMOR_KILL)) 42 + 43 + #define PROFILE_IS_HAT(_profile) ((_profile)->flags & PFLAG_HAT) 44 + 45 + /* 46 + * FIXME: currently need a clean way to replace and remove profiles as a 47 + * set. It should be done at the namespace level. 48 + * Either, with a set of profiles loaded at the namespace level or via 49 + * a mark and remove marked interface. 50 + */ 51 + enum profile_mode { 52 + APPARMOR_ENFORCE, /* enforce access rules */ 53 + APPARMOR_COMPLAIN, /* allow and log access violations */ 54 + APPARMOR_KILL, /* kill task on access violation */ 55 + }; 56 + 57 + enum profile_flags { 58 + PFLAG_HAT = 1, /* profile is a hat */ 59 + PFLAG_UNCONFINED = 2, /* profile is an unconfined profile */ 60 + PFLAG_NULL = 4, /* profile is null learning profile */ 61 + PFLAG_IX_ON_NAME_ERROR = 8, /* fallback to ix on name lookup fail */ 62 + PFLAG_IMMUTABLE = 0x10, /* don't allow changes/replacement */ 63 + PFLAG_USER_DEFINED = 0x20, /* user based profile - lower privs */ 64 + PFLAG_NO_LIST_REF = 0x40, /* list doesn't keep profile ref */ 65 + PFLAG_OLD_NULL_TRANS = 0x100, /* use // as the null transition */ 66 + 67 + /* These flags must correspond with PATH_flags */ 68 + PFLAG_MEDIATE_DELETED = 0x10000, /* mediate instead delegate deleted */ 69 + }; 70 + 71 + struct aa_profile; 72 + 73 + /* struct aa_policy - common part of both namespaces and profiles 74 + * @name: name of the object 75 + * @hname - The hierarchical name 76 + * @count: reference count of the obj 77 + * @list: list policy object is on 78 + * @profiles: head of the profiles list contained in the object 79 + */ 80 + struct aa_policy { 81 + char *name; 82 + char *hname; 83 + struct kref count; 84 + struct list_head list; 85 + struct list_head profiles; 86 + }; 87 + 88 + /* struct aa_ns_acct - accounting of profiles in namespace 89 + * @max_size: maximum space allowed for all profiles in namespace 90 + * @max_count: maximum number of profiles that can be in this namespace 91 + * @size: current size of profiles 92 + * @count: current count of profiles (includes null profiles) 93 + */ 94 + struct aa_ns_acct { 95 + int max_size; 96 + int max_count; 97 + int size; 98 + int count; 99 + }; 100 + 101 + /* struct aa_namespace - namespace for a set of profiles 102 + * @base: common policy 103 + * @parent: parent of namespace 104 + * @lock: lock for modifying the object 105 + * @acct: accounting for the namespace 106 + * @unconfined: special unconfined profile for the namespace 107 + * @sub_ns: list of namespaces under the current namespace. 108 + * 109 + * An aa_namespace defines the set profiles that are searched to determine 110 + * which profile to attach to a task. Profiles can not be shared between 111 + * aa_namespaces and profile names within a namespace are guaranteed to be 112 + * unique. When profiles in separate namespaces have the same name they 113 + * are NOT considered to be equivalent. 114 + * 115 + * Namespaces are hierarchical and only namespaces and profiles below the 116 + * current namespace are visible. 117 + * 118 + * Namespace names must be unique and can not contain the characters :/\0 119 + * 120 + * FIXME TODO: add vserver support of namespaces (can it all be done in 121 + * userspace?) 122 + */ 123 + struct aa_namespace { 124 + struct aa_policy base; 125 + struct aa_namespace *parent; 126 + rwlock_t lock; 127 + struct aa_ns_acct acct; 128 + struct aa_profile *unconfined; 129 + struct list_head sub_ns; 130 + }; 131 + 132 + /* struct aa_profile - basic confinement data 133 + * @base - base components of the profile (name, refcount, lists, lock ...) 134 + * @parent: parent of profile 135 + * @ns: namespace the profile is in 136 + * @replacedby: is set to the profile that replaced this profile 137 + * @rename: optional profile name that this profile renamed 138 + * @xmatch: optional extended matching for unconfined executables names 139 + * @xmatch_len: xmatch prefix len, used to determine xmatch priority 140 + * @sid: the unique security id number of this profile 141 + * @audit: the auditing mode of the profile 142 + * @mode: the enforcement mode of the profile 143 + * @flags: flags controlling profile behavior 144 + * @path_flags: flags controlling path generation behavior 145 + * @size: the memory consumed by this profiles rules 146 + * @file: The set of rules governing basic file access and domain transitions 147 + * @caps: capabilities for the profile 148 + * @rlimits: rlimits for the profile 149 + * 150 + * The AppArmor profile contains the basic confinement data. Each profile 151 + * has a name, and exists in a namespace. The @name and @exec_match are 152 + * used to determine profile attachment against unconfined tasks. All other 153 + * attachments are determined by profile X transition rules. 154 + * 155 + * The @replacedby field is write protected by the profile lock. Reads 156 + * are assumed to be atomic, and are done without locking. 157 + * 158 + * Profiles have a hierarchy where hats and children profiles keep 159 + * a reference to their parent. 160 + * 161 + * Profile names can not begin with a : and can not contain the \0 162 + * character. If a profile name begins with / it will be considered when 163 + * determining profile attachment on "unconfined" tasks. 164 + */ 165 + struct aa_profile { 166 + struct aa_policy base; 167 + struct aa_profile *parent; 168 + 169 + struct aa_namespace *ns; 170 + struct aa_profile *replacedby; 171 + const char *rename; 172 + 173 + struct aa_dfa *xmatch; 174 + int xmatch_len; 175 + u32 sid; 176 + enum audit_mode audit; 177 + enum profile_mode mode; 178 + u32 flags; 179 + u32 path_flags; 180 + int size; 181 + 182 + struct aa_file_rules file; 183 + struct aa_caps caps; 184 + struct aa_rlimit rlimits; 185 + }; 186 + 187 + extern struct aa_namespace *root_ns; 188 + extern enum profile_mode aa_g_profile_mode; 189 + 190 + void aa_add_profile(struct aa_policy *common, struct aa_profile *profile); 191 + 192 + bool aa_ns_visible(struct aa_namespace *curr, struct aa_namespace *view); 193 + const char *aa_ns_name(struct aa_namespace *parent, struct aa_namespace *child); 194 + int aa_alloc_root_ns(void); 195 + void aa_free_root_ns(void); 196 + void aa_free_namespace_kref(struct kref *kref); 197 + 198 + struct aa_namespace *aa_find_namespace(struct aa_namespace *root, 199 + const char *name); 200 + 201 + static inline struct aa_policy *aa_get_common(struct aa_policy *c) 202 + { 203 + if (c) 204 + kref_get(&c->count); 205 + 206 + return c; 207 + } 208 + 209 + /** 210 + * aa_get_namespace - increment references count on @ns 211 + * @ns: namespace to increment reference count of (MAYBE NULL) 212 + * 213 + * Returns: pointer to @ns, if @ns is NULL returns NULL 214 + * Requires: @ns must be held with valid refcount when called 215 + */ 216 + static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns) 217 + { 218 + if (ns) 219 + kref_get(&(ns->base.count)); 220 + 221 + return ns; 222 + } 223 + 224 + /** 225 + * aa_put_namespace - decrement refcount on @ns 226 + * @ns: namespace to put reference of 227 + * 228 + * Decrement reference count of @ns and if no longer in use free it 229 + */ 230 + static inline void aa_put_namespace(struct aa_namespace *ns) 231 + { 232 + if (ns) 233 + kref_put(&ns->base.count, aa_free_namespace_kref); 234 + } 235 + 236 + struct aa_profile *aa_alloc_profile(const char *name); 237 + struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat); 238 + void aa_free_profile_kref(struct kref *kref); 239 + struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name); 240 + struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *name); 241 + struct aa_profile *aa_match_profile(struct aa_namespace *ns, const char *name); 242 + 243 + ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace); 244 + ssize_t aa_remove_profiles(char *name, size_t size); 245 + 246 + #define PROF_ADD 1 247 + #define PROF_REPLACE 0 248 + 249 + #define unconfined(X) ((X)->flags & PFLAG_UNCONFINED) 250 + 251 + /** 252 + * aa_newest_version - find the newest version of @profile 253 + * @profile: the profile to check for newer versions of (NOT NULL) 254 + * 255 + * Returns: newest version of @profile, if @profile is the newest version 256 + * return @profile. 257 + * 258 + * NOTE: the profile returned is not refcounted, The refcount on @profile 259 + * must be held until the caller decides what to do with the returned newest 260 + * version. 261 + */ 262 + static inline struct aa_profile *aa_newest_version(struct aa_profile *profile) 263 + { 264 + while (profile->replacedby) 265 + profile = profile->replacedby; 266 + 267 + return profile; 268 + } 269 + 270 + /** 271 + * aa_get_profile - increment refcount on profile @p 272 + * @p: profile (MAYBE NULL) 273 + * 274 + * Returns: pointer to @p if @p is NULL will return NULL 275 + * Requires: @p must be held with valid refcount when called 276 + */ 277 + static inline struct aa_profile *aa_get_profile(struct aa_profile *p) 278 + { 279 + if (p) 280 + kref_get(&(p->base.count)); 281 + 282 + return p; 283 + } 284 + 285 + /** 286 + * aa_put_profile - decrement refcount on profile @p 287 + * @p: profile (MAYBE NULL) 288 + */ 289 + static inline void aa_put_profile(struct aa_profile *p) 290 + { 291 + if (p) 292 + kref_put(&p->base.count, aa_free_profile_kref); 293 + } 294 + 295 + static inline int AUDIT_MODE(struct aa_profile *profile) 296 + { 297 + if (aa_g_audit != AUDIT_NORMAL) 298 + return aa_g_audit; 299 + 300 + return profile->audit; 301 + } 302 + 303 + bool aa_may_manage_policy(int op); 304 + 305 + #endif /* __AA_POLICY_H */
+20
security/apparmor/include/policy_unpack.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor policy loading interface function definitions. 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #ifndef __POLICY_INTERFACE_H 16 + #define __POLICY_INTERFACE_H 17 + 18 + struct aa_profile *aa_unpack(void *udata, size_t size, const char **ns); 19 + 20 + #endif /* __POLICY_INTERFACE_H */
+26
security/apparmor/include/procattr.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor /proc/<pid>/attr/ interface function definitions. 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #ifndef __AA_PROCATTR_H 16 + #define __AA_PROCATTR_H 17 + 18 + #define AA_DO_TEST 1 19 + #define AA_ONEXEC 1 20 + 21 + int aa_getprocattr(struct aa_profile *profile, char **string); 22 + int aa_setprocattr_changehat(char *args, size_t size, int test); 23 + int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test); 24 + int aa_setprocattr_permipc(char *fqname); 25 + 26 + #endif /* __AA_PROCATTR_H */
+46
security/apparmor/include/resource.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor resource limits function definitions. 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #ifndef __AA_RESOURCE_H 16 + #define __AA_RESOURCE_H 17 + 18 + #include <linux/resource.h> 19 + #include <linux/sched.h> 20 + 21 + struct aa_profile; 22 + 23 + /* struct aa_rlimit - rlimit settings for the profile 24 + * @mask: which hard limits to set 25 + * @limits: rlimit values that override task limits 26 + * 27 + * AppArmor rlimits are used to set confined task rlimits. Only the 28 + * limits specified in @mask will be controlled by apparmor. 29 + */ 30 + struct aa_rlimit { 31 + unsigned int mask; 32 + struct rlimit limits[RLIM_NLIMITS]; 33 + }; 34 + 35 + int aa_map_resource(int resource); 36 + int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource, 37 + struct rlimit *new_rlim); 38 + 39 + void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new); 40 + 41 + static inline void aa_free_rlimit_rules(struct aa_rlimit *rlims) 42 + { 43 + /* NOP */ 44 + } 45 + 46 + #endif /* __AA_RESOURCE_H */
+24
security/apparmor/include/sid.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor security identifier (sid) definitions 5 + * 6 + * Copyright 2009-2010 Canonical Ltd. 7 + * 8 + * This program is free software; you can redistribute it and/or 9 + * modify it under the terms of the GNU General Public License as 10 + * published by the Free Software Foundation, version 2 of the 11 + * License. 12 + */ 13 + 14 + #ifndef __AA_SID_H 15 + #define __AA_SID_H 16 + 17 + #include <linux/types.h> 18 + 19 + struct aa_profile; 20 + 21 + u32 aa_alloc_sid(void); 22 + void aa_free_sid(u32 sid); 23 + 24 + #endif /* __AA_SID_H */
+114
security/apparmor/ipc.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor ipc mediation 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #include <linux/gfp.h> 16 + #include <linux/ptrace.h> 17 + 18 + #include "include/audit.h" 19 + #include "include/capability.h" 20 + #include "include/context.h" 21 + #include "include/policy.h" 22 + 23 + /* call back to audit ptrace fields */ 24 + static void audit_cb(struct audit_buffer *ab, void *va) 25 + { 26 + struct common_audit_data *sa = va; 27 + audit_log_format(ab, " target="); 28 + audit_log_untrustedstring(ab, sa->aad.target); 29 + } 30 + 31 + /** 32 + * aa_audit_ptrace - do auditing for ptrace 33 + * @profile: profile being enforced (NOT NULL) 34 + * @target: profile being traced (NOT NULL) 35 + * @error: error condition 36 + * 37 + * Returns: %0 or error code 38 + */ 39 + static int aa_audit_ptrace(struct aa_profile *profile, 40 + struct aa_profile *target, int error) 41 + { 42 + struct common_audit_data sa; 43 + COMMON_AUDIT_DATA_INIT(&sa, NONE); 44 + sa.aad.op = OP_PTRACE; 45 + sa.aad.target = target; 46 + sa.aad.error = error; 47 + 48 + return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_ATOMIC, &sa, 49 + audit_cb); 50 + } 51 + 52 + /** 53 + * aa_may_ptrace - test if tracer task can trace the tracee 54 + * @tracer_task: task who will do the tracing (NOT NULL) 55 + * @tracer: profile of the task doing the tracing (NOT NULL) 56 + * @tracee: task to be traced 57 + * @mode: whether PTRACE_MODE_READ || PTRACE_MODE_ATTACH 58 + * 59 + * Returns: %0 else error code if permission denied or error 60 + */ 61 + int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer, 62 + struct aa_profile *tracee, unsigned int mode) 63 + { 64 + /* TODO: currently only based on capability, not extended ptrace 65 + * rules, 66 + * Test mode for PTRACE_MODE_READ || PTRACE_MODE_ATTACH 67 + */ 68 + 69 + if (unconfined(tracer) || tracer == tracee) 70 + return 0; 71 + /* log this capability request */ 72 + return aa_capable(tracer_task, tracer, CAP_SYS_PTRACE, 1); 73 + } 74 + 75 + /** 76 + * aa_ptrace - do ptrace permission check and auditing 77 + * @tracer: task doing the tracing (NOT NULL) 78 + * @tracee: task being traced (NOT NULL) 79 + * @mode: ptrace mode either PTRACE_MODE_READ || PTRACE_MODE_ATTACH 80 + * 81 + * Returns: %0 else error code if permission denied or error 82 + */ 83 + int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee, 84 + unsigned int mode) 85 + { 86 + /* 87 + * tracer can ptrace tracee when 88 + * - tracer is unconfined || 89 + * - tracer is in complain mode 90 + * - tracer has rules allowing it to trace tracee currently this is: 91 + * - confined by the same profile || 92 + * - tracer profile has CAP_SYS_PTRACE 93 + */ 94 + 95 + struct aa_profile *tracer_p; 96 + /* cred released below */ 97 + const struct cred *cred = get_task_cred(tracer); 98 + int error = 0; 99 + tracer_p = aa_cred_profile(cred); 100 + 101 + if (!unconfined(tracer_p)) { 102 + /* lcred released below */ 103 + const struct cred *lcred = get_task_cred(tracee); 104 + struct aa_profile *tracee_p = aa_cred_profile(lcred); 105 + 106 + error = aa_may_ptrace(tracer, tracer_p, tracee_p, mode); 107 + error = aa_audit_ptrace(tracer_p, tracee_p, error); 108 + 109 + put_cred(lcred); 110 + } 111 + put_cred(cred); 112 + 113 + return error; 114 + }
+133
security/apparmor/lib.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains basic common functions used in AppArmor 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #include <linux/slab.h> 16 + #include <linux/string.h> 17 + #include <linux/vmalloc.h> 18 + 19 + #include "include/audit.h" 20 + 21 + 22 + /** 23 + * aa_split_fqname - split a fqname into a profile and namespace name 24 + * @fqname: a full qualified name in namespace profile format (NOT NULL) 25 + * @ns_name: pointer to portion of the string containing the ns name (NOT NULL) 26 + * 27 + * Returns: profile name or NULL if one is not specified 28 + * 29 + * Split a namespace name from a profile name (see policy.c for naming 30 + * description). If a portion of the name is missing it returns NULL for 31 + * that portion. 32 + * 33 + * NOTE: may modify the @fqname string. The pointers returned point 34 + * into the @fqname string. 35 + */ 36 + char *aa_split_fqname(char *fqname, char **ns_name) 37 + { 38 + char *name = strim(fqname); 39 + 40 + *ns_name = NULL; 41 + if (name[0] == ':') { 42 + char *split = strchr(&name[1], ':'); 43 + if (split) { 44 + /* overwrite ':' with \0 */ 45 + *split = 0; 46 + name = skip_spaces(split + 1); 47 + } else 48 + /* a ns name without a following profile is allowed */ 49 + name = NULL; 50 + *ns_name = &name[1]; 51 + } 52 + if (name && *name == 0) 53 + name = NULL; 54 + 55 + return name; 56 + } 57 + 58 + /** 59 + * aa_info_message - log a none profile related status message 60 + * @str: message to log 61 + */ 62 + void aa_info_message(const char *str) 63 + { 64 + if (audit_enabled) { 65 + struct common_audit_data sa; 66 + COMMON_AUDIT_DATA_INIT(&sa, NONE); 67 + sa.aad.info = str; 68 + aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL); 69 + } 70 + printk(KERN_INFO "AppArmor: %s\n", str); 71 + } 72 + 73 + /** 74 + * kvmalloc - do allocation preferring kmalloc but falling back to vmalloc 75 + * @size: size of allocation 76 + * 77 + * Return: allocated buffer or NULL if failed 78 + * 79 + * It is possible that policy being loaded from the user is larger than 80 + * what can be allocated by kmalloc, in those cases fall back to vmalloc. 81 + */ 82 + void *kvmalloc(size_t size) 83 + { 84 + void *buffer = NULL; 85 + 86 + if (size == 0) 87 + return NULL; 88 + 89 + /* do not attempt kmalloc if we need more than 16 pages at once */ 90 + if (size <= (16*PAGE_SIZE)) 91 + buffer = kmalloc(size, GFP_NOIO | __GFP_NOWARN); 92 + if (!buffer) { 93 + /* see kvfree for why size must be at least work_struct size 94 + * when allocated via vmalloc 95 + */ 96 + if (size < sizeof(struct work_struct)) 97 + size = sizeof(struct work_struct); 98 + buffer = vmalloc(size); 99 + } 100 + return buffer; 101 + } 102 + 103 + /** 104 + * do_vfree - workqueue routine for freeing vmalloced memory 105 + * @work: data to be freed 106 + * 107 + * The work_struct is overlaid to the data being freed, as at the point 108 + * the work is scheduled the data is no longer valid, be its freeing 109 + * needs to be delayed until safe. 110 + */ 111 + static void do_vfree(struct work_struct *work) 112 + { 113 + vfree(work); 114 + } 115 + 116 + /** 117 + * kvfree - free an allocation do by kvmalloc 118 + * @buffer: buffer to free (MAYBE_NULL) 119 + * 120 + * Free a buffer allocated by kvmalloc 121 + */ 122 + void kvfree(void *buffer) 123 + { 124 + if (is_vmalloc_addr(buffer)) { 125 + /* Data is no longer valid so just use the allocated space 126 + * as the work_struct 127 + */ 128 + struct work_struct *work = (struct work_struct *) buffer; 129 + INIT_WORK(work, do_vfree); 130 + schedule_work(work); 131 + } else 132 + kfree(buffer); 133 + }
+938
security/apparmor/lsm.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor LSM hooks. 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #include <linux/security.h> 16 + #include <linux/moduleparam.h> 17 + #include <linux/mm.h> 18 + #include <linux/mman.h> 19 + #include <linux/mount.h> 20 + #include <linux/namei.h> 21 + #include <linux/ptrace.h> 22 + #include <linux/ctype.h> 23 + #include <linux/sysctl.h> 24 + #include <linux/audit.h> 25 + #include <net/sock.h> 26 + 27 + #include "include/apparmor.h" 28 + #include "include/apparmorfs.h" 29 + #include "include/audit.h" 30 + #include "include/capability.h" 31 + #include "include/context.h" 32 + #include "include/file.h" 33 + #include "include/ipc.h" 34 + #include "include/path.h" 35 + #include "include/policy.h" 36 + #include "include/procattr.h" 37 + 38 + /* Flag indicating whether initialization completed */ 39 + int apparmor_initialized __initdata; 40 + 41 + /* 42 + * LSM hook functions 43 + */ 44 + 45 + /* 46 + * free the associated aa_task_cxt and put its profiles 47 + */ 48 + static void apparmor_cred_free(struct cred *cred) 49 + { 50 + aa_free_task_context(cred->security); 51 + cred->security = NULL; 52 + } 53 + 54 + /* 55 + * allocate the apparmor part of blank credentials 56 + */ 57 + static int apparmor_cred_alloc_blank(struct cred *cred, gfp_t gfp) 58 + { 59 + /* freed by apparmor_cred_free */ 60 + struct aa_task_cxt *cxt = aa_alloc_task_context(gfp); 61 + if (!cxt) 62 + return -ENOMEM; 63 + 64 + cred->security = cxt; 65 + return 0; 66 + } 67 + 68 + /* 69 + * prepare new aa_task_cxt for modification by prepare_cred block 70 + */ 71 + static int apparmor_cred_prepare(struct cred *new, const struct cred *old, 72 + gfp_t gfp) 73 + { 74 + /* freed by apparmor_cred_free */ 75 + struct aa_task_cxt *cxt = aa_alloc_task_context(gfp); 76 + if (!cxt) 77 + return -ENOMEM; 78 + 79 + aa_dup_task_context(cxt, old->security); 80 + new->security = cxt; 81 + return 0; 82 + } 83 + 84 + /* 85 + * transfer the apparmor data to a blank set of creds 86 + */ 87 + static void apparmor_cred_transfer(struct cred *new, const struct cred *old) 88 + { 89 + const struct aa_task_cxt *old_cxt = old->security; 90 + struct aa_task_cxt *new_cxt = new->security; 91 + 92 + aa_dup_task_context(new_cxt, old_cxt); 93 + } 94 + 95 + static int apparmor_ptrace_access_check(struct task_struct *child, 96 + unsigned int mode) 97 + { 98 + int error = cap_ptrace_access_check(child, mode); 99 + if (error) 100 + return error; 101 + 102 + return aa_ptrace(current, child, mode); 103 + } 104 + 105 + static int apparmor_ptrace_traceme(struct task_struct *parent) 106 + { 107 + int error = cap_ptrace_traceme(parent); 108 + if (error) 109 + return error; 110 + 111 + return aa_ptrace(parent, current, PTRACE_MODE_ATTACH); 112 + } 113 + 114 + /* Derived from security/commoncap.c:cap_capget */ 115 + static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, 116 + kernel_cap_t *inheritable, kernel_cap_t *permitted) 117 + { 118 + struct aa_profile *profile; 119 + const struct cred *cred; 120 + 121 + rcu_read_lock(); 122 + cred = __task_cred(target); 123 + profile = aa_cred_profile(cred); 124 + 125 + *effective = cred->cap_effective; 126 + *inheritable = cred->cap_inheritable; 127 + *permitted = cred->cap_permitted; 128 + 129 + if (!unconfined(profile)) { 130 + *effective = cap_intersect(*effective, profile->caps.allow); 131 + *permitted = cap_intersect(*permitted, profile->caps.allow); 132 + } 133 + rcu_read_unlock(); 134 + 135 + return 0; 136 + } 137 + 138 + static int apparmor_capable(struct task_struct *task, const struct cred *cred, 139 + int cap, int audit) 140 + { 141 + struct aa_profile *profile; 142 + /* cap_capable returns 0 on success, else -EPERM */ 143 + int error = cap_capable(task, cred, cap, audit); 144 + if (!error) { 145 + profile = aa_cred_profile(cred); 146 + if (!unconfined(profile)) 147 + error = aa_capable(task, profile, cap, audit); 148 + } 149 + return error; 150 + } 151 + 152 + /** 153 + * common_perm - basic common permission check wrapper fn for paths 154 + * @op: operation being checked 155 + * @path: path to check permission of (NOT NULL) 156 + * @mask: requested permissions mask 157 + * @cond: conditional info for the permission request (NOT NULL) 158 + * 159 + * Returns: %0 else error code if error or permission denied 160 + */ 161 + static int common_perm(int op, struct path *path, u32 mask, 162 + struct path_cond *cond) 163 + { 164 + struct aa_profile *profile; 165 + int error = 0; 166 + 167 + profile = __aa_current_profile(); 168 + if (!unconfined(profile)) 169 + error = aa_path_perm(op, profile, path, 0, mask, cond); 170 + 171 + return error; 172 + } 173 + 174 + /** 175 + * common_perm_dir_dentry - common permission wrapper when path is dir, dentry 176 + * @op: operation being checked 177 + * @dir: directory of the dentry (NOT NULL) 178 + * @dentry: dentry to check (NOT NULL) 179 + * @mask: requested permissions mask 180 + * @cond: conditional info for the permission request (NOT NULL) 181 + * 182 + * Returns: %0 else error code if error or permission denied 183 + */ 184 + static int common_perm_dir_dentry(int op, struct path *dir, 185 + struct dentry *dentry, u32 mask, 186 + struct path_cond *cond) 187 + { 188 + struct path path = { dir->mnt, dentry }; 189 + 190 + return common_perm(op, &path, mask, cond); 191 + } 192 + 193 + /** 194 + * common_perm_mnt_dentry - common permission wrapper when mnt, dentry 195 + * @op: operation being checked 196 + * @mnt: mount point of dentry (NOT NULL) 197 + * @dentry: dentry to check (NOT NULL) 198 + * @mask: requested permissions mask 199 + * 200 + * Returns: %0 else error code if error or permission denied 201 + */ 202 + static int common_perm_mnt_dentry(int op, struct vfsmount *mnt, 203 + struct dentry *dentry, u32 mask) 204 + { 205 + struct path path = { mnt, dentry }; 206 + struct path_cond cond = { dentry->d_inode->i_uid, 207 + dentry->d_inode->i_mode 208 + }; 209 + 210 + return common_perm(op, &path, mask, &cond); 211 + } 212 + 213 + /** 214 + * common_perm_rm - common permission wrapper for operations doing rm 215 + * @op: operation being checked 216 + * @dir: directory that the dentry is in (NOT NULL) 217 + * @dentry: dentry being rm'd (NOT NULL) 218 + * @mask: requested permission mask 219 + * 220 + * Returns: %0 else error code if error or permission denied 221 + */ 222 + static int common_perm_rm(int op, struct path *dir, 223 + struct dentry *dentry, u32 mask) 224 + { 225 + struct inode *inode = dentry->d_inode; 226 + struct path_cond cond = { }; 227 + 228 + if (!inode || !dir->mnt || !mediated_filesystem(inode)) 229 + return 0; 230 + 231 + cond.uid = inode->i_uid; 232 + cond.mode = inode->i_mode; 233 + 234 + return common_perm_dir_dentry(op, dir, dentry, mask, &cond); 235 + } 236 + 237 + /** 238 + * common_perm_create - common permission wrapper for operations doing create 239 + * @op: operation being checked 240 + * @dir: directory that dentry will be created in (NOT NULL) 241 + * @dentry: dentry to create (NOT NULL) 242 + * @mask: request permission mask 243 + * @mode: created file mode 244 + * 245 + * Returns: %0 else error code if error or permission denied 246 + */ 247 + static int common_perm_create(int op, struct path *dir, struct dentry *dentry, 248 + u32 mask, umode_t mode) 249 + { 250 + struct path_cond cond = { current_fsuid(), mode }; 251 + 252 + if (!dir->mnt || !mediated_filesystem(dir->dentry->d_inode)) 253 + return 0; 254 + 255 + return common_perm_dir_dentry(op, dir, dentry, mask, &cond); 256 + } 257 + 258 + static int apparmor_path_unlink(struct path *dir, struct dentry *dentry) 259 + { 260 + return common_perm_rm(OP_UNLINK, dir, dentry, AA_MAY_DELETE); 261 + } 262 + 263 + static int apparmor_path_mkdir(struct path *dir, struct dentry *dentry, 264 + int mode) 265 + { 266 + return common_perm_create(OP_MKDIR, dir, dentry, AA_MAY_CREATE, 267 + S_IFDIR); 268 + } 269 + 270 + static int apparmor_path_rmdir(struct path *dir, struct dentry *dentry) 271 + { 272 + return common_perm_rm(OP_RMDIR, dir, dentry, AA_MAY_DELETE); 273 + } 274 + 275 + static int apparmor_path_mknod(struct path *dir, struct dentry *dentry, 276 + int mode, unsigned int dev) 277 + { 278 + return common_perm_create(OP_MKNOD, dir, dentry, AA_MAY_CREATE, mode); 279 + } 280 + 281 + static int apparmor_path_truncate(struct path *path) 282 + { 283 + struct path_cond cond = { path->dentry->d_inode->i_uid, 284 + path->dentry->d_inode->i_mode 285 + }; 286 + 287 + if (!path->mnt || !mediated_filesystem(path->dentry->d_inode)) 288 + return 0; 289 + 290 + return common_perm(OP_TRUNC, path, MAY_WRITE | AA_MAY_META_WRITE, 291 + &cond); 292 + } 293 + 294 + static int apparmor_path_symlink(struct path *dir, struct dentry *dentry, 295 + const char *old_name) 296 + { 297 + return common_perm_create(OP_SYMLINK, dir, dentry, AA_MAY_CREATE, 298 + S_IFLNK); 299 + } 300 + 301 + static int apparmor_path_link(struct dentry *old_dentry, struct path *new_dir, 302 + struct dentry *new_dentry) 303 + { 304 + struct aa_profile *profile; 305 + int error = 0; 306 + 307 + if (!mediated_filesystem(old_dentry->d_inode)) 308 + return 0; 309 + 310 + profile = aa_current_profile(); 311 + if (!unconfined(profile)) 312 + error = aa_path_link(profile, old_dentry, new_dir, new_dentry); 313 + return error; 314 + } 315 + 316 + static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry, 317 + struct path *new_dir, struct dentry *new_dentry) 318 + { 319 + struct aa_profile *profile; 320 + int error = 0; 321 + 322 + if (!mediated_filesystem(old_dentry->d_inode)) 323 + return 0; 324 + 325 + profile = aa_current_profile(); 326 + if (!unconfined(profile)) { 327 + struct path old_path = { old_dir->mnt, old_dentry }; 328 + struct path new_path = { new_dir->mnt, new_dentry }; 329 + struct path_cond cond = { old_dentry->d_inode->i_uid, 330 + old_dentry->d_inode->i_mode 331 + }; 332 + 333 + error = aa_path_perm(OP_RENAME_SRC, profile, &old_path, 0, 334 + MAY_READ | AA_MAY_META_READ | MAY_WRITE | 335 + AA_MAY_META_WRITE | AA_MAY_DELETE, 336 + &cond); 337 + if (!error) 338 + error = aa_path_perm(OP_RENAME_DEST, profile, &new_path, 339 + 0, MAY_WRITE | AA_MAY_META_WRITE | 340 + AA_MAY_CREATE, &cond); 341 + 342 + } 343 + return error; 344 + } 345 + 346 + static int apparmor_path_chmod(struct dentry *dentry, struct vfsmount *mnt, 347 + mode_t mode) 348 + { 349 + if (!mediated_filesystem(dentry->d_inode)) 350 + return 0; 351 + 352 + return common_perm_mnt_dentry(OP_CHMOD, mnt, dentry, AA_MAY_CHMOD); 353 + } 354 + 355 + static int apparmor_path_chown(struct path *path, uid_t uid, gid_t gid) 356 + { 357 + struct path_cond cond = { path->dentry->d_inode->i_uid, 358 + path->dentry->d_inode->i_mode 359 + }; 360 + 361 + if (!mediated_filesystem(path->dentry->d_inode)) 362 + return 0; 363 + 364 + return common_perm(OP_CHOWN, path, AA_MAY_CHOWN, &cond); 365 + } 366 + 367 + static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) 368 + { 369 + if (!mediated_filesystem(dentry->d_inode)) 370 + return 0; 371 + 372 + return common_perm_mnt_dentry(OP_GETATTR, mnt, dentry, 373 + AA_MAY_META_READ); 374 + } 375 + 376 + static int apparmor_dentry_open(struct file *file, const struct cred *cred) 377 + { 378 + struct aa_file_cxt *fcxt = file->f_security; 379 + struct aa_profile *profile; 380 + int error = 0; 381 + 382 + if (!mediated_filesystem(file->f_path.dentry->d_inode)) 383 + return 0; 384 + 385 + /* If in exec, permission is handled by bprm hooks. 386 + * Cache permissions granted by the previous exec check, with 387 + * implicit read and executable mmap which are required to 388 + * actually execute the image. 389 + */ 390 + if (current->in_execve) { 391 + fcxt->allow = MAY_EXEC | MAY_READ | AA_EXEC_MMAP; 392 + return 0; 393 + } 394 + 395 + profile = aa_cred_profile(cred); 396 + if (!unconfined(profile)) { 397 + struct inode *inode = file->f_path.dentry->d_inode; 398 + struct path_cond cond = { inode->i_uid, inode->i_mode }; 399 + 400 + error = aa_path_perm(OP_OPEN, profile, &file->f_path, 0, 401 + aa_map_file_to_perms(file), &cond); 402 + /* todo cache full allowed permissions set and state */ 403 + fcxt->allow = aa_map_file_to_perms(file); 404 + } 405 + 406 + return error; 407 + } 408 + 409 + static int apparmor_file_alloc_security(struct file *file) 410 + { 411 + /* freed by apparmor_file_free_security */ 412 + file->f_security = aa_alloc_file_context(GFP_KERNEL); 413 + if (!file->f_security) 414 + return -ENOMEM; 415 + return 0; 416 + 417 + } 418 + 419 + static void apparmor_file_free_security(struct file *file) 420 + { 421 + struct aa_file_cxt *cxt = file->f_security; 422 + 423 + aa_free_file_context(cxt); 424 + } 425 + 426 + static int common_file_perm(int op, struct file *file, u32 mask) 427 + { 428 + struct aa_file_cxt *fcxt = file->f_security; 429 + struct aa_profile *profile, *fprofile = aa_cred_profile(file->f_cred); 430 + int error = 0; 431 + 432 + BUG_ON(!fprofile); 433 + 434 + if (!file->f_path.mnt || 435 + !mediated_filesystem(file->f_path.dentry->d_inode)) 436 + return 0; 437 + 438 + profile = __aa_current_profile(); 439 + 440 + /* revalidate access, if task is unconfined, or the cached cred 441 + * doesn't match or if the request is for more permissions than 442 + * was granted. 443 + * 444 + * Note: the test for !unconfined(fprofile) is to handle file 445 + * delegation from unconfined tasks 446 + */ 447 + if (!unconfined(profile) && !unconfined(fprofile) && 448 + ((fprofile != profile) || (mask & ~fcxt->allow))) 449 + error = aa_file_perm(op, profile, file, mask); 450 + 451 + return error; 452 + } 453 + 454 + static int apparmor_file_permission(struct file *file, int mask) 455 + { 456 + return common_file_perm(OP_FPERM, file, mask); 457 + } 458 + 459 + static int apparmor_file_lock(struct file *file, unsigned int cmd) 460 + { 461 + u32 mask = AA_MAY_LOCK; 462 + 463 + if (cmd == F_WRLCK) 464 + mask |= MAY_WRITE; 465 + 466 + return common_file_perm(OP_FLOCK, file, mask); 467 + } 468 + 469 + static int common_mmap(int op, struct file *file, unsigned long prot, 470 + unsigned long flags) 471 + { 472 + struct dentry *dentry; 473 + int mask = 0; 474 + 475 + if (!file || !file->f_security) 476 + return 0; 477 + 478 + if (prot & PROT_READ) 479 + mask |= MAY_READ; 480 + /* 481 + * Private mappings don't require write perms since they don't 482 + * write back to the files 483 + */ 484 + if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE)) 485 + mask |= MAY_WRITE; 486 + if (prot & PROT_EXEC) 487 + mask |= AA_EXEC_MMAP; 488 + 489 + dentry = file->f_path.dentry; 490 + return common_file_perm(op, file, mask); 491 + } 492 + 493 + static int apparmor_file_mmap(struct file *file, unsigned long reqprot, 494 + unsigned long prot, unsigned long flags, 495 + unsigned long addr, unsigned long addr_only) 496 + { 497 + int rc = 0; 498 + 499 + /* do DAC check */ 500 + rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); 501 + if (rc || addr_only) 502 + return rc; 503 + 504 + return common_mmap(OP_FMMAP, file, prot, flags); 505 + } 506 + 507 + static int apparmor_file_mprotect(struct vm_area_struct *vma, 508 + unsigned long reqprot, unsigned long prot) 509 + { 510 + return common_mmap(OP_FMPROT, vma->vm_file, prot, 511 + !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0); 512 + } 513 + 514 + static int apparmor_getprocattr(struct task_struct *task, char *name, 515 + char **value) 516 + { 517 + int error = -ENOENT; 518 + struct aa_profile *profile; 519 + /* released below */ 520 + const struct cred *cred = get_task_cred(task); 521 + struct aa_task_cxt *cxt = cred->security; 522 + profile = aa_cred_profile(cred); 523 + 524 + if (strcmp(name, "current") == 0) 525 + error = aa_getprocattr(aa_newest_version(cxt->profile), 526 + value); 527 + else if (strcmp(name, "prev") == 0 && cxt->previous) 528 + error = aa_getprocattr(aa_newest_version(cxt->previous), 529 + value); 530 + else if (strcmp(name, "exec") == 0 && cxt->onexec) 531 + error = aa_getprocattr(aa_newest_version(cxt->onexec), 532 + value); 533 + else 534 + error = -EINVAL; 535 + 536 + put_cred(cred); 537 + 538 + return error; 539 + } 540 + 541 + static int apparmor_setprocattr(struct task_struct *task, char *name, 542 + void *value, size_t size) 543 + { 544 + char *command, *args = value; 545 + size_t arg_size; 546 + int error; 547 + 548 + if (size == 0) 549 + return -EINVAL; 550 + /* args points to a PAGE_SIZE buffer, AppArmor requires that 551 + * the buffer must be null terminated or have size <= PAGE_SIZE -1 552 + * so that AppArmor can null terminate them 553 + */ 554 + if (args[size - 1] != '\0') { 555 + if (size == PAGE_SIZE) 556 + return -EINVAL; 557 + args[size] = '\0'; 558 + } 559 + 560 + /* task can only write its own attributes */ 561 + if (current != task) 562 + return -EACCES; 563 + 564 + args = value; 565 + args = strim(args); 566 + command = strsep(&args, " "); 567 + if (!args) 568 + return -EINVAL; 569 + args = skip_spaces(args); 570 + if (!*args) 571 + return -EINVAL; 572 + 573 + arg_size = size - (args - (char *) value); 574 + if (strcmp(name, "current") == 0) { 575 + if (strcmp(command, "changehat") == 0) { 576 + error = aa_setprocattr_changehat(args, arg_size, 577 + !AA_DO_TEST); 578 + } else if (strcmp(command, "permhat") == 0) { 579 + error = aa_setprocattr_changehat(args, arg_size, 580 + AA_DO_TEST); 581 + } else if (strcmp(command, "changeprofile") == 0) { 582 + error = aa_setprocattr_changeprofile(args, !AA_ONEXEC, 583 + !AA_DO_TEST); 584 + } else if (strcmp(command, "permprofile") == 0) { 585 + error = aa_setprocattr_changeprofile(args, !AA_ONEXEC, 586 + AA_DO_TEST); 587 + } else if (strcmp(command, "permipc") == 0) { 588 + error = aa_setprocattr_permipc(args); 589 + } else { 590 + struct common_audit_data sa; 591 + COMMON_AUDIT_DATA_INIT(&sa, NONE); 592 + sa.aad.op = OP_SETPROCATTR; 593 + sa.aad.info = name; 594 + sa.aad.error = -EINVAL; 595 + return aa_audit(AUDIT_APPARMOR_DENIED, NULL, GFP_KERNEL, 596 + &sa, NULL); 597 + } 598 + } else if (strcmp(name, "exec") == 0) { 599 + error = aa_setprocattr_changeprofile(args, AA_ONEXEC, 600 + !AA_DO_TEST); 601 + } else { 602 + /* only support the "current" and "exec" process attributes */ 603 + return -EINVAL; 604 + } 605 + if (!error) 606 + error = size; 607 + return error; 608 + } 609 + 610 + static int apparmor_task_setrlimit(unsigned int resource, 611 + struct rlimit *new_rlim) 612 + { 613 + struct aa_profile *profile = aa_current_profile(); 614 + int error = 0; 615 + 616 + if (!unconfined(profile)) 617 + error = aa_task_setrlimit(profile, resource, new_rlim); 618 + 619 + return error; 620 + } 621 + 622 + static struct security_operations apparmor_ops = { 623 + .name = "apparmor", 624 + 625 + .ptrace_access_check = apparmor_ptrace_access_check, 626 + .ptrace_traceme = apparmor_ptrace_traceme, 627 + .capget = apparmor_capget, 628 + .capable = apparmor_capable, 629 + 630 + .path_link = apparmor_path_link, 631 + .path_unlink = apparmor_path_unlink, 632 + .path_symlink = apparmor_path_symlink, 633 + .path_mkdir = apparmor_path_mkdir, 634 + .path_rmdir = apparmor_path_rmdir, 635 + .path_mknod = apparmor_path_mknod, 636 + .path_rename = apparmor_path_rename, 637 + .path_chmod = apparmor_path_chmod, 638 + .path_chown = apparmor_path_chown, 639 + .path_truncate = apparmor_path_truncate, 640 + .dentry_open = apparmor_dentry_open, 641 + .inode_getattr = apparmor_inode_getattr, 642 + 643 + .file_permission = apparmor_file_permission, 644 + .file_alloc_security = apparmor_file_alloc_security, 645 + .file_free_security = apparmor_file_free_security, 646 + .file_mmap = apparmor_file_mmap, 647 + .file_mprotect = apparmor_file_mprotect, 648 + .file_lock = apparmor_file_lock, 649 + 650 + .getprocattr = apparmor_getprocattr, 651 + .setprocattr = apparmor_setprocattr, 652 + 653 + .cred_alloc_blank = apparmor_cred_alloc_blank, 654 + .cred_free = apparmor_cred_free, 655 + .cred_prepare = apparmor_cred_prepare, 656 + .cred_transfer = apparmor_cred_transfer, 657 + 658 + .bprm_set_creds = apparmor_bprm_set_creds, 659 + .bprm_committing_creds = apparmor_bprm_committing_creds, 660 + .bprm_committed_creds = apparmor_bprm_committed_creds, 661 + .bprm_secureexec = apparmor_bprm_secureexec, 662 + 663 + .task_setrlimit = apparmor_task_setrlimit, 664 + }; 665 + 666 + /* 667 + * AppArmor sysfs module parameters 668 + */ 669 + 670 + static int param_set_aabool(const char *val, struct kernel_param *kp); 671 + static int param_get_aabool(char *buffer, struct kernel_param *kp); 672 + #define param_check_aabool(name, p) __param_check(name, p, int) 673 + 674 + static int param_set_aauint(const char *val, struct kernel_param *kp); 675 + static int param_get_aauint(char *buffer, struct kernel_param *kp); 676 + #define param_check_aauint(name, p) __param_check(name, p, int) 677 + 678 + static int param_set_aalockpolicy(const char *val, struct kernel_param *kp); 679 + static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp); 680 + #define param_check_aalockpolicy(name, p) __param_check(name, p, int) 681 + 682 + static int param_set_audit(const char *val, struct kernel_param *kp); 683 + static int param_get_audit(char *buffer, struct kernel_param *kp); 684 + #define param_check_audit(name, p) __param_check(name, p, int) 685 + 686 + static int param_set_mode(const char *val, struct kernel_param *kp); 687 + static int param_get_mode(char *buffer, struct kernel_param *kp); 688 + #define param_check_mode(name, p) __param_check(name, p, int) 689 + 690 + /* Flag values, also controllable via /sys/module/apparmor/parameters 691 + * We define special types as we want to do additional mediation. 692 + */ 693 + 694 + /* AppArmor global enforcement switch - complain, enforce, kill */ 695 + enum profile_mode aa_g_profile_mode = APPARMOR_ENFORCE; 696 + module_param_call(mode, param_set_mode, param_get_mode, 697 + &aa_g_profile_mode, S_IRUSR | S_IWUSR); 698 + 699 + /* Debug mode */ 700 + int aa_g_debug; 701 + module_param_named(debug, aa_g_debug, aabool, S_IRUSR | S_IWUSR); 702 + 703 + /* Audit mode */ 704 + enum audit_mode aa_g_audit; 705 + module_param_call(audit, param_set_audit, param_get_audit, 706 + &aa_g_audit, S_IRUSR | S_IWUSR); 707 + 708 + /* Determines if audit header is included in audited messages. This 709 + * provides more context if the audit daemon is not running 710 + */ 711 + int aa_g_audit_header = 1; 712 + module_param_named(audit_header, aa_g_audit_header, aabool, 713 + S_IRUSR | S_IWUSR); 714 + 715 + /* lock out loading/removal of policy 716 + * TODO: add in at boot loading of policy, which is the only way to 717 + * load policy, if lock_policy is set 718 + */ 719 + int aa_g_lock_policy; 720 + module_param_named(lock_policy, aa_g_lock_policy, aalockpolicy, 721 + S_IRUSR | S_IWUSR); 722 + 723 + /* Syscall logging mode */ 724 + int aa_g_logsyscall; 725 + module_param_named(logsyscall, aa_g_logsyscall, aabool, S_IRUSR | S_IWUSR); 726 + 727 + /* Maximum pathname length before accesses will start getting rejected */ 728 + unsigned int aa_g_path_max = 2 * PATH_MAX; 729 + module_param_named(path_max, aa_g_path_max, aauint, S_IRUSR | S_IWUSR); 730 + 731 + /* Determines how paranoid loading of policy is and how much verification 732 + * on the loaded policy is done. 733 + */ 734 + int aa_g_paranoid_load = 1; 735 + module_param_named(paranoid_load, aa_g_paranoid_load, aabool, 736 + S_IRUSR | S_IWUSR); 737 + 738 + /* Boot time disable flag */ 739 + static unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE; 740 + module_param_named(enabled, apparmor_enabled, aabool, S_IRUSR); 741 + 742 + static int __init apparmor_enabled_setup(char *str) 743 + { 744 + unsigned long enabled; 745 + int error = strict_strtoul(str, 0, &enabled); 746 + if (!error) 747 + apparmor_enabled = enabled ? 1 : 0; 748 + return 1; 749 + } 750 + 751 + __setup("apparmor=", apparmor_enabled_setup); 752 + 753 + /* set global flag turning off the ability to load policy */ 754 + static int param_set_aalockpolicy(const char *val, struct kernel_param *kp) 755 + { 756 + if (!capable(CAP_MAC_ADMIN)) 757 + return -EPERM; 758 + if (aa_g_lock_policy) 759 + return -EACCES; 760 + return param_set_bool(val, kp); 761 + } 762 + 763 + static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp) 764 + { 765 + if (!capable(CAP_MAC_ADMIN)) 766 + return -EPERM; 767 + return param_get_bool(buffer, kp); 768 + } 769 + 770 + static int param_set_aabool(const char *val, struct kernel_param *kp) 771 + { 772 + if (!capable(CAP_MAC_ADMIN)) 773 + return -EPERM; 774 + return param_set_bool(val, kp); 775 + } 776 + 777 + static int param_get_aabool(char *buffer, struct kernel_param *kp) 778 + { 779 + if (!capable(CAP_MAC_ADMIN)) 780 + return -EPERM; 781 + return param_get_bool(buffer, kp); 782 + } 783 + 784 + static int param_set_aauint(const char *val, struct kernel_param *kp) 785 + { 786 + if (!capable(CAP_MAC_ADMIN)) 787 + return -EPERM; 788 + return param_set_uint(val, kp); 789 + } 790 + 791 + static int param_get_aauint(char *buffer, struct kernel_param *kp) 792 + { 793 + if (!capable(CAP_MAC_ADMIN)) 794 + return -EPERM; 795 + return param_get_uint(buffer, kp); 796 + } 797 + 798 + static int param_get_audit(char *buffer, struct kernel_param *kp) 799 + { 800 + if (!capable(CAP_MAC_ADMIN)) 801 + return -EPERM; 802 + 803 + if (!apparmor_enabled) 804 + return -EINVAL; 805 + 806 + return sprintf(buffer, "%s", audit_mode_names[aa_g_audit]); 807 + } 808 + 809 + static int param_set_audit(const char *val, struct kernel_param *kp) 810 + { 811 + int i; 812 + if (!capable(CAP_MAC_ADMIN)) 813 + return -EPERM; 814 + 815 + if (!apparmor_enabled) 816 + return -EINVAL; 817 + 818 + if (!val) 819 + return -EINVAL; 820 + 821 + for (i = 0; i < AUDIT_MAX_INDEX; i++) { 822 + if (strcmp(val, audit_mode_names[i]) == 0) { 823 + aa_g_audit = i; 824 + return 0; 825 + } 826 + } 827 + 828 + return -EINVAL; 829 + } 830 + 831 + static int param_get_mode(char *buffer, struct kernel_param *kp) 832 + { 833 + if (!capable(CAP_MAC_ADMIN)) 834 + return -EPERM; 835 + 836 + if (!apparmor_enabled) 837 + return -EINVAL; 838 + 839 + return sprintf(buffer, "%s", profile_mode_names[aa_g_profile_mode]); 840 + } 841 + 842 + static int param_set_mode(const char *val, struct kernel_param *kp) 843 + { 844 + int i; 845 + if (!capable(CAP_MAC_ADMIN)) 846 + return -EPERM; 847 + 848 + if (!apparmor_enabled) 849 + return -EINVAL; 850 + 851 + if (!val) 852 + return -EINVAL; 853 + 854 + for (i = 0; i < APPARMOR_NAMES_MAX_INDEX; i++) { 855 + if (strcmp(val, profile_mode_names[i]) == 0) { 856 + aa_g_profile_mode = i; 857 + return 0; 858 + } 859 + } 860 + 861 + return -EINVAL; 862 + } 863 + 864 + /* 865 + * AppArmor init functions 866 + */ 867 + 868 + /** 869 + * set_init_cxt - set a task context and profile on the first task. 870 + * 871 + * TODO: allow setting an alternate profile than unconfined 872 + */ 873 + static int __init set_init_cxt(void) 874 + { 875 + struct cred *cred = (struct cred *)current->real_cred; 876 + struct aa_task_cxt *cxt; 877 + 878 + cxt = aa_alloc_task_context(GFP_KERNEL); 879 + if (!cxt) 880 + return -ENOMEM; 881 + 882 + cxt->profile = aa_get_profile(root_ns->unconfined); 883 + cred->security = cxt; 884 + 885 + return 0; 886 + } 887 + 888 + static int __init apparmor_init(void) 889 + { 890 + int error; 891 + 892 + if (!apparmor_enabled || !security_module_enable(&apparmor_ops)) { 893 + aa_info_message("AppArmor disabled by boot time parameter"); 894 + apparmor_enabled = 0; 895 + return 0; 896 + } 897 + 898 + error = aa_alloc_root_ns(); 899 + if (error) { 900 + AA_ERROR("Unable to allocate default profile namespace\n"); 901 + goto alloc_out; 902 + } 903 + 904 + error = set_init_cxt(); 905 + if (error) { 906 + AA_ERROR("Failed to set context on init task\n"); 907 + goto register_security_out; 908 + } 909 + 910 + error = register_security(&apparmor_ops); 911 + if (error) { 912 + AA_ERROR("Unable to register AppArmor\n"); 913 + goto register_security_out; 914 + } 915 + 916 + /* Report that AppArmor successfully initialized */ 917 + apparmor_initialized = 1; 918 + if (aa_g_profile_mode == APPARMOR_COMPLAIN) 919 + aa_info_message("AppArmor initialized: complain mode enabled"); 920 + else if (aa_g_profile_mode == APPARMOR_KILL) 921 + aa_info_message("AppArmor initialized: kill mode enabled"); 922 + else 923 + aa_info_message("AppArmor initialized"); 924 + 925 + return error; 926 + 927 + register_security_out: 928 + aa_free_root_ns(); 929 + 930 + alloc_out: 931 + aa_destroy_aafs(); 932 + 933 + apparmor_enabled = 0; 934 + return error; 935 + 936 + } 937 + 938 + security_initcall(apparmor_init);
+353
security/apparmor/match.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor dfa based regular expression matching engine 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #include <linux/errno.h> 16 + #include <linux/kernel.h> 17 + #include <linux/mm.h> 18 + #include <linux/slab.h> 19 + #include <linux/vmalloc.h> 20 + #include <linux/err.h> 21 + #include <linux/kref.h> 22 + 23 + #include "include/apparmor.h" 24 + #include "include/match.h" 25 + 26 + /** 27 + * unpack_table - unpack a dfa table (one of accept, default, base, next check) 28 + * @blob: data to unpack (NOT NULL) 29 + * @bsize: size of blob 30 + * 31 + * Returns: pointer to table else NULL on failure 32 + * 33 + * NOTE: must be freed by kvfree (not kmalloc) 34 + */ 35 + static struct table_header *unpack_table(char *blob, size_t bsize) 36 + { 37 + struct table_header *table = NULL; 38 + struct table_header th; 39 + size_t tsize; 40 + 41 + if (bsize < sizeof(struct table_header)) 42 + goto out; 43 + 44 + /* loaded td_id's start at 1, subtract 1 now to avoid doing 45 + * it every time we use td_id as an index 46 + */ 47 + th.td_id = be16_to_cpu(*(u16 *) (blob)) - 1; 48 + th.td_flags = be16_to_cpu(*(u16 *) (blob + 2)); 49 + th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8)); 50 + blob += sizeof(struct table_header); 51 + 52 + if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 || 53 + th.td_flags == YYTD_DATA8)) 54 + goto out; 55 + 56 + tsize = table_size(th.td_lolen, th.td_flags); 57 + if (bsize < tsize) 58 + goto out; 59 + 60 + table = kvmalloc(tsize); 61 + if (table) { 62 + *table = th; 63 + if (th.td_flags == YYTD_DATA8) 64 + UNPACK_ARRAY(table->td_data, blob, th.td_lolen, 65 + u8, byte_to_byte); 66 + else if (th.td_flags == YYTD_DATA16) 67 + UNPACK_ARRAY(table->td_data, blob, th.td_lolen, 68 + u16, be16_to_cpu); 69 + else if (th.td_flags == YYTD_DATA32) 70 + UNPACK_ARRAY(table->td_data, blob, th.td_lolen, 71 + u32, be32_to_cpu); 72 + else 73 + goto fail; 74 + } 75 + 76 + out: 77 + /* if table was vmalloced make sure the page tables are synced 78 + * before it is used, as it goes live to all cpus. 79 + */ 80 + if (is_vmalloc_addr(table)) 81 + vm_unmap_aliases(); 82 + return table; 83 + fail: 84 + kvfree(table); 85 + return NULL; 86 + } 87 + 88 + /** 89 + * verify_dfa - verify that transitions and states in the tables are in bounds. 90 + * @dfa: dfa to test (NOT NULL) 91 + * @flags: flags controlling what type of accept table are acceptable 92 + * 93 + * Assumes dfa has gone through the first pass verification done by unpacking 94 + * NOTE: this does not valid accept table values 95 + * 96 + * Returns: %0 else error code on failure to verify 97 + */ 98 + static int verify_dfa(struct aa_dfa *dfa, int flags) 99 + { 100 + size_t i, state_count, trans_count; 101 + int error = -EPROTO; 102 + 103 + /* check that required tables exist */ 104 + if (!(dfa->tables[YYTD_ID_DEF] && 105 + dfa->tables[YYTD_ID_BASE] && 106 + dfa->tables[YYTD_ID_NXT] && dfa->tables[YYTD_ID_CHK])) 107 + goto out; 108 + 109 + /* accept.size == default.size == base.size */ 110 + state_count = dfa->tables[YYTD_ID_BASE]->td_lolen; 111 + if (ACCEPT1_FLAGS(flags)) { 112 + if (!dfa->tables[YYTD_ID_ACCEPT]) 113 + goto out; 114 + if (state_count != dfa->tables[YYTD_ID_ACCEPT]->td_lolen) 115 + goto out; 116 + } 117 + if (ACCEPT2_FLAGS(flags)) { 118 + if (!dfa->tables[YYTD_ID_ACCEPT2]) 119 + goto out; 120 + if (state_count != dfa->tables[YYTD_ID_ACCEPT2]->td_lolen) 121 + goto out; 122 + } 123 + if (state_count != dfa->tables[YYTD_ID_DEF]->td_lolen) 124 + goto out; 125 + 126 + /* next.size == chk.size */ 127 + trans_count = dfa->tables[YYTD_ID_NXT]->td_lolen; 128 + if (trans_count != dfa->tables[YYTD_ID_CHK]->td_lolen) 129 + goto out; 130 + 131 + /* if equivalence classes then its table size must be 256 */ 132 + if (dfa->tables[YYTD_ID_EC] && 133 + dfa->tables[YYTD_ID_EC]->td_lolen != 256) 134 + goto out; 135 + 136 + if (flags & DFA_FLAG_VERIFY_STATES) { 137 + for (i = 0; i < state_count; i++) { 138 + if (DEFAULT_TABLE(dfa)[i] >= state_count) 139 + goto out; 140 + /* TODO: do check that DEF state recursion terminates */ 141 + if (BASE_TABLE(dfa)[i] + 255 >= trans_count) { 142 + printk(KERN_ERR "AppArmor DFA next/check upper " 143 + "bounds error\n"); 144 + goto out; 145 + } 146 + } 147 + 148 + for (i = 0; i < trans_count; i++) { 149 + if (NEXT_TABLE(dfa)[i] >= state_count) 150 + goto out; 151 + if (CHECK_TABLE(dfa)[i] >= state_count) 152 + goto out; 153 + } 154 + } 155 + 156 + error = 0; 157 + out: 158 + return error; 159 + } 160 + 161 + /** 162 + * dfa_free - free a dfa allocated by aa_dfa_unpack 163 + * @dfa: the dfa to free (MAYBE NULL) 164 + * 165 + * Requires: reference count to dfa == 0 166 + */ 167 + static void dfa_free(struct aa_dfa *dfa) 168 + { 169 + if (dfa) { 170 + int i; 171 + 172 + for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) { 173 + kvfree(dfa->tables[i]); 174 + dfa->tables[i] = NULL; 175 + } 176 + kfree(dfa); 177 + } 178 + } 179 + 180 + /** 181 + * aa_dfa_free_kref - free aa_dfa by kref (called by aa_put_dfa) 182 + * @kr: kref callback for freeing of a dfa (NOT NULL) 183 + */ 184 + void aa_dfa_free_kref(struct kref *kref) 185 + { 186 + struct aa_dfa *dfa = container_of(kref, struct aa_dfa, count); 187 + dfa_free(dfa); 188 + } 189 + 190 + /** 191 + * aa_dfa_unpack - unpack the binary tables of a serialized dfa 192 + * @blob: aligned serialized stream of data to unpack (NOT NULL) 193 + * @size: size of data to unpack 194 + * @flags: flags controlling what type of accept tables are acceptable 195 + * 196 + * Unpack a dfa that has been serialized. To find information on the dfa 197 + * format look in Documentation/apparmor.txt 198 + * Assumes the dfa @blob stream has been aligned on a 8 byte boundry 199 + * 200 + * Returns: an unpacked dfa ready for matching or ERR_PTR on failure 201 + */ 202 + struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags) 203 + { 204 + int hsize; 205 + int error = -ENOMEM; 206 + char *data = blob; 207 + struct table_header *table = NULL; 208 + struct aa_dfa *dfa = kzalloc(sizeof(struct aa_dfa), GFP_KERNEL); 209 + if (!dfa) 210 + goto fail; 211 + 212 + kref_init(&dfa->count); 213 + 214 + error = -EPROTO; 215 + 216 + /* get dfa table set header */ 217 + if (size < sizeof(struct table_set_header)) 218 + goto fail; 219 + 220 + if (ntohl(*(u32 *) data) != YYTH_MAGIC) 221 + goto fail; 222 + 223 + hsize = ntohl(*(u32 *) (data + 4)); 224 + if (size < hsize) 225 + goto fail; 226 + 227 + dfa->flags = ntohs(*(u16 *) (data + 12)); 228 + data += hsize; 229 + size -= hsize; 230 + 231 + while (size > 0) { 232 + table = unpack_table(data, size); 233 + if (!table) 234 + goto fail; 235 + 236 + switch (table->td_id) { 237 + case YYTD_ID_ACCEPT: 238 + if (!(table->td_flags & ACCEPT1_FLAGS(flags))) 239 + goto fail; 240 + break; 241 + case YYTD_ID_ACCEPT2: 242 + if (!(table->td_flags & ACCEPT2_FLAGS(flags))) 243 + goto fail; 244 + break; 245 + case YYTD_ID_BASE: 246 + if (table->td_flags != YYTD_DATA32) 247 + goto fail; 248 + break; 249 + case YYTD_ID_DEF: 250 + case YYTD_ID_NXT: 251 + case YYTD_ID_CHK: 252 + if (table->td_flags != YYTD_DATA16) 253 + goto fail; 254 + break; 255 + case YYTD_ID_EC: 256 + if (table->td_flags != YYTD_DATA8) 257 + goto fail; 258 + break; 259 + default: 260 + goto fail; 261 + } 262 + /* check for duplicate table entry */ 263 + if (dfa->tables[table->td_id]) 264 + goto fail; 265 + dfa->tables[table->td_id] = table; 266 + data += table_size(table->td_lolen, table->td_flags); 267 + size -= table_size(table->td_lolen, table->td_flags); 268 + table = NULL; 269 + } 270 + 271 + error = verify_dfa(dfa, flags); 272 + if (error) 273 + goto fail; 274 + 275 + return dfa; 276 + 277 + fail: 278 + kvfree(table); 279 + dfa_free(dfa); 280 + return ERR_PTR(error); 281 + } 282 + 283 + /** 284 + * aa_dfa_match_len - traverse @dfa to find state @str stops at 285 + * @dfa: the dfa to match @str against (NOT NULL) 286 + * @start: the state of the dfa to start matching in 287 + * @str: the string of bytes to match against the dfa (NOT NULL) 288 + * @len: length of the string of bytes to match 289 + * 290 + * aa_dfa_match_len will match @str against the dfa and return the state it 291 + * finished matching in. The final state can be used to look up the accepting 292 + * label, or as the start state of a continuing match. 293 + * 294 + * This function will happily match again the 0 byte and only finishes 295 + * when @len input is consumed. 296 + * 297 + * Returns: final state reached after input is consumed 298 + */ 299 + unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start, 300 + const char *str, int len) 301 + { 302 + u16 *def = DEFAULT_TABLE(dfa); 303 + u32 *base = BASE_TABLE(dfa); 304 + u16 *next = NEXT_TABLE(dfa); 305 + u16 *check = CHECK_TABLE(dfa); 306 + unsigned int state = start, pos; 307 + 308 + if (state == 0) 309 + return 0; 310 + 311 + /* current state is <state>, matching character *str */ 312 + if (dfa->tables[YYTD_ID_EC]) { 313 + /* Equivalence class table defined */ 314 + u8 *equiv = EQUIV_TABLE(dfa); 315 + /* default is direct to next state */ 316 + for (; len; len--) { 317 + pos = base[state] + equiv[(u8) *str++]; 318 + if (check[pos] == state) 319 + state = next[pos]; 320 + else 321 + state = def[state]; 322 + } 323 + } else { 324 + /* default is direct to next state */ 325 + for (; len; len--) { 326 + pos = base[state] + (u8) *str++; 327 + if (check[pos] == state) 328 + state = next[pos]; 329 + else 330 + state = def[state]; 331 + } 332 + } 333 + 334 + return state; 335 + } 336 + 337 + /** 338 + * aa_dfa_next_state - traverse @dfa to find state @str stops at 339 + * @dfa: the dfa to match @str against (NOT NULL) 340 + * @start: the state of the dfa to start matching in 341 + * @str: the null terminated string of bytes to match against the dfa (NOT NULL) 342 + * 343 + * aa_dfa_next_state will match @str against the dfa and return the state it 344 + * finished matching in. The final state can be used to look up the accepting 345 + * label, or as the start state of a continuing match. 346 + * 347 + * Returns: final state reached after input is consumed 348 + */ 349 + unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start, 350 + const char *str) 351 + { 352 + return aa_dfa_match_len(dfa, start, str, strlen(str)); 353 + }
+235
security/apparmor/path.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor function for pathnames 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #include <linux/magic.h> 16 + #include <linux/mnt_namespace.h> 17 + #include <linux/mount.h> 18 + #include <linux/namei.h> 19 + #include <linux/nsproxy.h> 20 + #include <linux/path.h> 21 + #include <linux/sched.h> 22 + #include <linux/slab.h> 23 + #include <linux/fs_struct.h> 24 + 25 + #include "include/apparmor.h" 26 + #include "include/path.h" 27 + #include "include/policy.h" 28 + 29 + 30 + /* modified from dcache.c */ 31 + static int prepend(char **buffer, int buflen, const char *str, int namelen) 32 + { 33 + buflen -= namelen; 34 + if (buflen < 0) 35 + return -ENAMETOOLONG; 36 + *buffer -= namelen; 37 + memcpy(*buffer, str, namelen); 38 + return 0; 39 + } 40 + 41 + #define CHROOT_NSCONNECT (PATH_CHROOT_REL | PATH_CHROOT_NSCONNECT) 42 + 43 + /** 44 + * d_namespace_path - lookup a name associated with a given path 45 + * @path: path to lookup (NOT NULL) 46 + * @buf: buffer to store path to (NOT NULL) 47 + * @buflen: length of @buf 48 + * @name: Returns - pointer for start of path name with in @buf (NOT NULL) 49 + * @flags: flags controlling path lookup 50 + * 51 + * Handle path name lookup. 52 + * 53 + * Returns: %0 else error code if path lookup fails 54 + * When no error the path name is returned in @name which points to 55 + * to a position in @buf 56 + */ 57 + static int d_namespace_path(struct path *path, char *buf, int buflen, 58 + char **name, int flags) 59 + { 60 + struct path root, tmp; 61 + char *res; 62 + int deleted, connected; 63 + int error = 0; 64 + 65 + /* Get the root we want to resolve too */ 66 + if (flags & PATH_CHROOT_REL) { 67 + /* resolve paths relative to chroot */ 68 + read_lock(&current->fs->lock); 69 + root = current->fs->root; 70 + /* released below */ 71 + path_get(&root); 72 + read_unlock(&current->fs->lock); 73 + } else { 74 + /* resolve paths relative to namespace */ 75 + root.mnt = current->nsproxy->mnt_ns->root; 76 + root.dentry = root.mnt->mnt_root; 77 + /* released below */ 78 + path_get(&root); 79 + } 80 + 81 + spin_lock(&dcache_lock); 82 + /* There is a race window between path lookup here and the 83 + * need to strip the " (deleted) string that __d_path applies 84 + * Detect the race and relookup the path 85 + * 86 + * The stripping of (deleted) is a hack that could be removed 87 + * with an updated __d_path 88 + */ 89 + do { 90 + tmp = root; 91 + deleted = d_unlinked(path->dentry); 92 + res = __d_path(path, &tmp, buf, buflen); 93 + 94 + } while (deleted != d_unlinked(path->dentry)); 95 + spin_unlock(&dcache_lock); 96 + 97 + *name = res; 98 + /* handle error conditions - and still allow a partial path to 99 + * be returned. 100 + */ 101 + if (IS_ERR(res)) { 102 + error = PTR_ERR(res); 103 + *name = buf; 104 + goto out; 105 + } 106 + if (deleted) { 107 + /* On some filesystems, newly allocated dentries appear to the 108 + * security_path hooks as a deleted dentry except without an 109 + * inode allocated. 110 + * 111 + * Remove the appended deleted text and return as string for 112 + * normal mediation, or auditing. The (deleted) string is 113 + * guaranteed to be added in this case, so just strip it. 114 + */ 115 + buf[buflen - 11] = 0; /* - (len(" (deleted)") +\0) */ 116 + 117 + if (path->dentry->d_inode && !(flags & PATH_MEDIATE_DELETED)) { 118 + error = -ENOENT; 119 + goto out; 120 + } 121 + } 122 + 123 + /* Determine if the path is connected to the expected root */ 124 + connected = tmp.dentry == root.dentry && tmp.mnt == root.mnt; 125 + 126 + /* If the path is not connected, 127 + * check if it is a sysctl and handle specially else remove any 128 + * leading / that __d_path may have returned. 129 + * Unless 130 + * specifically directed to connect the path, 131 + * OR 132 + * if in a chroot and doing chroot relative paths and the path 133 + * resolves to the namespace root (would be connected outside 134 + * of chroot) and specifically directed to connect paths to 135 + * namespace root. 136 + */ 137 + if (!connected) { 138 + /* is the disconnect path a sysctl? */ 139 + if (tmp.dentry->d_sb->s_magic == PROC_SUPER_MAGIC && 140 + strncmp(*name, "/sys/", 5) == 0) { 141 + /* TODO: convert over to using a per namespace 142 + * control instead of hard coded /proc 143 + */ 144 + error = prepend(name, *name - buf, "/proc", 5); 145 + } else if (!(flags & PATH_CONNECT_PATH) && 146 + !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) && 147 + (tmp.mnt == current->nsproxy->mnt_ns->root && 148 + tmp.dentry == tmp.mnt->mnt_root))) { 149 + /* disconnected path, don't return pathname starting 150 + * with '/' 151 + */ 152 + error = -ESTALE; 153 + if (*res == '/') 154 + *name = res + 1; 155 + } 156 + } 157 + 158 + out: 159 + path_put(&root); 160 + 161 + return error; 162 + } 163 + 164 + /** 165 + * get_name_to_buffer - get the pathname to a buffer ensure dir / is appended 166 + * @path: path to get name for (NOT NULL) 167 + * @flags: flags controlling path lookup 168 + * @buffer: buffer to put name in (NOT NULL) 169 + * @size: size of buffer 170 + * @name: Returns - contains position of path name in @buffer (NOT NULL) 171 + * 172 + * Returns: %0 else error on failure 173 + */ 174 + static int get_name_to_buffer(struct path *path, int flags, char *buffer, 175 + int size, char **name) 176 + { 177 + int adjust = (flags & PATH_IS_DIR) ? 1 : 0; 178 + int error = d_namespace_path(path, buffer, size - adjust, name, flags); 179 + 180 + if (!error && (flags & PATH_IS_DIR) && (*name)[1] != '\0') 181 + /* 182 + * Append "/" to the pathname. The root directory is a special 183 + * case; it already ends in slash. 184 + */ 185 + strcpy(&buffer[size - 2], "/"); 186 + 187 + return error; 188 + } 189 + 190 + /** 191 + * aa_get_name - compute the pathname of a file 192 + * @path: path the file (NOT NULL) 193 + * @flags: flags controlling path name generation 194 + * @buffer: buffer that aa_get_name() allocated (NOT NULL) 195 + * @name: Returns - the generated path name if !error (NOT NULL) 196 + * 197 + * @name is a pointer to the beginning of the pathname (which usually differs 198 + * from the beginning of the buffer), or NULL. If there is an error @name 199 + * may contain a partial or invalid name that can be used for audit purposes, 200 + * but it can not be used for mediation. 201 + * 202 + * We need PATH_IS_DIR to indicate whether the file is a directory or not 203 + * because the file may not yet exist, and so we cannot check the inode's 204 + * file type. 205 + * 206 + * Returns: %0 else error code if could retrieve name 207 + */ 208 + int aa_get_name(struct path *path, int flags, char **buffer, const char **name) 209 + { 210 + char *buf, *str = NULL; 211 + int size = 256; 212 + int error; 213 + 214 + *name = NULL; 215 + *buffer = NULL; 216 + for (;;) { 217 + /* freed by caller */ 218 + buf = kmalloc(size, GFP_KERNEL); 219 + if (!buf) 220 + return -ENOMEM; 221 + 222 + error = get_name_to_buffer(path, flags, buf, size, &str); 223 + if (error != -ENAMETOOLONG) 224 + break; 225 + 226 + kfree(buf); 227 + size <<= 1; 228 + if (size > aa_g_path_max) 229 + return -ENAMETOOLONG; 230 + } 231 + *buffer = buf; 232 + *name = str; 233 + 234 + return error; 235 + }
+1184
security/apparmor/policy.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor policy manipulation functions 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + * 14 + * 15 + * AppArmor policy is based around profiles, which contain the rules a 16 + * task is confined by. Every task in the system has a profile attached 17 + * to it determined either by matching "unconfined" tasks against the 18 + * visible set of profiles or by following a profiles attachment rules. 19 + * 20 + * Each profile exists in a profile namespace which is a container of 21 + * visible profiles. Each namespace contains a special "unconfined" profile, 22 + * which doesn't enforce any confinement on a task beyond DAC. 23 + * 24 + * Namespace and profile names can be written together in either 25 + * of two syntaxes. 26 + * :namespace:profile - used by kernel interfaces for easy detection 27 + * namespace://profile - used by policy 28 + * 29 + * Profile names can not start with : or @ or ^ and may not contain \0 30 + * 31 + * Reserved profile names 32 + * unconfined - special automatically generated unconfined profile 33 + * inherit - special name to indicate profile inheritance 34 + * null-XXXX-YYYY - special automatically generated learning profiles 35 + * 36 + * Namespace names may not start with / or @ and may not contain \0 or : 37 + * Reserved namespace names 38 + * user-XXXX - user defined profiles 39 + * 40 + * a // in a profile or namespace name indicates a hierarchical name with the 41 + * name before the // being the parent and the name after the child. 42 + * 43 + * Profile and namespace hierarchies serve two different but similar purposes. 44 + * The namespace contains the set of visible profiles that are considered 45 + * for attachment. The hierarchy of namespaces allows for virtualizing 46 + * the namespace so that for example a chroot can have its own set of profiles 47 + * which may define some local user namespaces. 48 + * The profile hierarchy severs two distinct purposes, 49 + * - it allows for sub profiles or hats, which allows an application to run 50 + * subprograms under its own profile with different restriction than it 51 + * self, and not have it use the system profile. 52 + * eg. if a mail program starts an editor, the policy might make the 53 + * restrictions tighter on the editor tighter than the mail program, 54 + * and definitely different than general editor restrictions 55 + * - it allows for binary hierarchy of profiles, so that execution history 56 + * is preserved. This feature isn't exploited by AppArmor reference policy 57 + * but is allowed. NOTE: this is currently suboptimal because profile 58 + * aliasing is not currently implemented so that a profile for each 59 + * level must be defined. 60 + * eg. /bin/bash///bin/ls as a name would indicate /bin/ls was started 61 + * from /bin/bash 62 + * 63 + * A profile or namespace name that can contain one or more // separators 64 + * is referred to as an hname (hierarchical). 65 + * eg. /bin/bash//bin/ls 66 + * 67 + * An fqname is a name that may contain both namespace and profile hnames. 68 + * eg. :ns:/bin/bash//bin/ls 69 + * 70 + * NOTES: 71 + * - locking of profile lists is currently fairly coarse. All profile 72 + * lists within a namespace use the namespace lock. 73 + * FIXME: move profile lists to using rcu_lists 74 + */ 75 + 76 + #include <linux/slab.h> 77 + #include <linux/spinlock.h> 78 + #include <linux/string.h> 79 + 80 + #include "include/apparmor.h" 81 + #include "include/capability.h" 82 + #include "include/context.h" 83 + #include "include/file.h" 84 + #include "include/ipc.h" 85 + #include "include/match.h" 86 + #include "include/path.h" 87 + #include "include/policy.h" 88 + #include "include/policy_unpack.h" 89 + #include "include/resource.h" 90 + #include "include/sid.h" 91 + 92 + 93 + /* root profile namespace */ 94 + struct aa_namespace *root_ns; 95 + 96 + const char *profile_mode_names[] = { 97 + "enforce", 98 + "complain", 99 + "kill", 100 + }; 101 + 102 + /** 103 + * hname_tail - find the last component of an hname 104 + * @name: hname to find the base profile name component of (NOT NULL) 105 + * 106 + * Returns: the tail (base profile name) name component of an hname 107 + */ 108 + static const char *hname_tail(const char *hname) 109 + { 110 + char *split; 111 + hname = strim((char *)hname); 112 + for (split = strstr(hname, "//"); split; split = strstr(hname, "//")) 113 + hname = split + 2; 114 + 115 + return hname; 116 + } 117 + 118 + /** 119 + * policy_init - initialize a policy structure 120 + * @policy: policy to initialize (NOT NULL) 121 + * @prefix: prefix name if any is required. (MAYBE NULL) 122 + * @name: name of the policy, init will make a copy of it (NOT NULL) 123 + * 124 + * Note: this fn creates a copy of strings passed in 125 + * 126 + * Returns: true if policy init successful 127 + */ 128 + static bool policy_init(struct aa_policy *policy, const char *prefix, 129 + const char *name) 130 + { 131 + /* freed by policy_free */ 132 + if (prefix) { 133 + policy->hname = kmalloc(strlen(prefix) + strlen(name) + 3, 134 + GFP_KERNEL); 135 + if (policy->hname) 136 + sprintf(policy->hname, "%s//%s", prefix, name); 137 + } else 138 + policy->hname = kstrdup(name, GFP_KERNEL); 139 + if (!policy->hname) 140 + return 0; 141 + /* base.name is a substring of fqname */ 142 + policy->name = (char *)hname_tail(policy->hname); 143 + INIT_LIST_HEAD(&policy->list); 144 + INIT_LIST_HEAD(&policy->profiles); 145 + kref_init(&policy->count); 146 + 147 + return 1; 148 + } 149 + 150 + /** 151 + * policy_destroy - free the elements referenced by @policy 152 + * @policy: policy that is to have its elements freed (NOT NULL) 153 + */ 154 + static void policy_destroy(struct aa_policy *policy) 155 + { 156 + /* still contains profiles -- invalid */ 157 + if (!list_empty(&policy->profiles)) { 158 + AA_ERROR("%s: internal error, " 159 + "policy '%s' still contains profiles\n", 160 + __func__, policy->name); 161 + BUG(); 162 + } 163 + if (!list_empty(&policy->list)) { 164 + AA_ERROR("%s: internal error, policy '%s' still on list\n", 165 + __func__, policy->name); 166 + BUG(); 167 + } 168 + 169 + /* don't free name as its a subset of hname */ 170 + kzfree(policy->hname); 171 + } 172 + 173 + /** 174 + * __policy_find - find a policy by @name on a policy list 175 + * @head: list to search (NOT NULL) 176 + * @name: name to search for (NOT NULL) 177 + * 178 + * Requires: correct locks for the @head list be held 179 + * 180 + * Returns: unrefcounted policy that match @name or NULL if not found 181 + */ 182 + static struct aa_policy *__policy_find(struct list_head *head, const char *name) 183 + { 184 + struct aa_policy *policy; 185 + 186 + list_for_each_entry(policy, head, list) { 187 + if (!strcmp(policy->name, name)) 188 + return policy; 189 + } 190 + return NULL; 191 + } 192 + 193 + /** 194 + * __policy_strn_find - find a policy that's name matches @len chars of @str 195 + * @head: list to search (NOT NULL) 196 + * @str: string to search for (NOT NULL) 197 + * @len: length of match required 198 + * 199 + * Requires: correct locks for the @head list be held 200 + * 201 + * Returns: unrefcounted policy that match @str or NULL if not found 202 + * 203 + * if @len == strlen(@strlen) then this is equiv to __policy_find 204 + * other wise it allows searching for policy by a partial match of name 205 + */ 206 + static struct aa_policy *__policy_strn_find(struct list_head *head, 207 + const char *str, int len) 208 + { 209 + struct aa_policy *policy; 210 + 211 + list_for_each_entry(policy, head, list) { 212 + if (aa_strneq(policy->name, str, len)) 213 + return policy; 214 + } 215 + 216 + return NULL; 217 + } 218 + 219 + /* 220 + * Routines for AppArmor namespaces 221 + */ 222 + 223 + static const char *hidden_ns_name = "---"; 224 + /** 225 + * aa_ns_visible - test if @view is visible from @curr 226 + * @curr: namespace to treat as the parent (NOT NULL) 227 + * @view: namespace to test if visible from @curr (NOT NULL) 228 + * 229 + * Returns: true if @view is visible from @curr else false 230 + */ 231 + bool aa_ns_visible(struct aa_namespace *curr, struct aa_namespace *view) 232 + { 233 + if (curr == view) 234 + return true; 235 + 236 + for ( ; view; view = view->parent) { 237 + if (view->parent == curr) 238 + return true; 239 + } 240 + return false; 241 + } 242 + 243 + /** 244 + * aa_na_name - Find the ns name to display for @view from @curr 245 + * @curr - current namespace (NOT NULL) 246 + * @view - namespace attempting to view (NOT NULL) 247 + * 248 + * Returns: name of @view visible from @curr 249 + */ 250 + const char *aa_ns_name(struct aa_namespace *curr, struct aa_namespace *view) 251 + { 252 + /* if view == curr then the namespace name isn't displayed */ 253 + if (curr == view) 254 + return ""; 255 + 256 + if (aa_ns_visible(curr, view)) { 257 + /* at this point if a ns is visible it is in a view ns 258 + * thus the curr ns.hname is a prefix of its name. 259 + * Only output the virtualized portion of the name 260 + * Add + 2 to skip over // separating curr hname prefix 261 + * from the visible tail of the views hname 262 + */ 263 + return view->base.hname + strlen(curr->base.hname) + 2; 264 + } else 265 + return hidden_ns_name; 266 + } 267 + 268 + /** 269 + * alloc_namespace - allocate, initialize and return a new namespace 270 + * @prefix: parent namespace name (MAYBE NULL) 271 + * @name: a preallocated name (NOT NULL) 272 + * 273 + * Returns: refcounted namespace or NULL on failure. 274 + */ 275 + static struct aa_namespace *alloc_namespace(const char *prefix, 276 + const char *name) 277 + { 278 + struct aa_namespace *ns; 279 + 280 + ns = kzalloc(sizeof(*ns), GFP_KERNEL); 281 + AA_DEBUG("%s(%p)\n", __func__, ns); 282 + if (!ns) 283 + return NULL; 284 + if (!policy_init(&ns->base, prefix, name)) 285 + goto fail_ns; 286 + 287 + INIT_LIST_HEAD(&ns->sub_ns); 288 + rwlock_init(&ns->lock); 289 + 290 + /* released by free_namespace */ 291 + ns->unconfined = aa_alloc_profile("unconfined"); 292 + if (!ns->unconfined) 293 + goto fail_unconfined; 294 + 295 + ns->unconfined->sid = aa_alloc_sid(); 296 + ns->unconfined->flags = PFLAG_UNCONFINED | PFLAG_IX_ON_NAME_ERROR | 297 + PFLAG_IMMUTABLE; 298 + 299 + /* 300 + * released by free_namespace, however __remove_namespace breaks 301 + * the cyclic references (ns->unconfined, and unconfined->ns) and 302 + * replaces with refs to parent namespace unconfined 303 + */ 304 + ns->unconfined->ns = aa_get_namespace(ns); 305 + 306 + return ns; 307 + 308 + fail_unconfined: 309 + kzfree(ns->base.name); 310 + fail_ns: 311 + kzfree(ns); 312 + return NULL; 313 + } 314 + 315 + /** 316 + * free_namespace - free a profile namespace 317 + * @ns: the namespace to free (MAYBE NULL) 318 + * 319 + * Requires: All references to the namespace must have been put, if the 320 + * namespace was referenced by a profile confining a task, 321 + */ 322 + static void free_namespace(struct aa_namespace *ns) 323 + { 324 + if (!ns) 325 + return; 326 + 327 + policy_destroy(&ns->base); 328 + aa_put_namespace(ns->parent); 329 + 330 + if (ns->unconfined && ns->unconfined->ns == ns) 331 + ns->unconfined->ns = NULL; 332 + 333 + aa_put_profile(ns->unconfined); 334 + kzfree(ns); 335 + } 336 + 337 + /** 338 + * aa_free_namespace_kref - free aa_namespace by kref (see aa_put_namespace) 339 + * @kr: kref callback for freeing of a namespace (NOT NULL) 340 + */ 341 + void aa_free_namespace_kref(struct kref *kref) 342 + { 343 + free_namespace(container_of(kref, struct aa_namespace, base.count)); 344 + } 345 + 346 + /** 347 + * __aa_find_namespace - find a namespace on a list by @name 348 + * @head: list to search for namespace on (NOT NULL) 349 + * @name: name of namespace to look for (NOT NULL) 350 + * 351 + * Returns: unrefcounted namespace 352 + * 353 + * Requires: ns lock be held 354 + */ 355 + static struct aa_namespace *__aa_find_namespace(struct list_head *head, 356 + const char *name) 357 + { 358 + return (struct aa_namespace *)__policy_find(head, name); 359 + } 360 + 361 + /** 362 + * aa_find_namespace - look up a profile namespace on the namespace list 363 + * @root: namespace to search in (NOT NULL) 364 + * @name: name of namespace to find (NOT NULL) 365 + * 366 + * Returns: a refcounted namespace on the list, or NULL if no namespace 367 + * called @name exists. 368 + * 369 + * refcount released by caller 370 + */ 371 + struct aa_namespace *aa_find_namespace(struct aa_namespace *root, 372 + const char *name) 373 + { 374 + struct aa_namespace *ns = NULL; 375 + 376 + read_lock(&root->lock); 377 + ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name)); 378 + read_unlock(&root->lock); 379 + 380 + return ns; 381 + } 382 + 383 + /** 384 + * aa_prepare_namespace - find an existing or create a new namespace of @name 385 + * @name: the namespace to find or add (MAYBE NULL) 386 + * 387 + * Returns: refcounted namespace or NULL if failed to create one 388 + */ 389 + static struct aa_namespace *aa_prepare_namespace(const char *name) 390 + { 391 + struct aa_namespace *ns, *root; 392 + 393 + root = aa_current_profile()->ns; 394 + 395 + write_lock(&root->lock); 396 + 397 + /* if name isn't specified the profile is loaded to the current ns */ 398 + if (!name) { 399 + /* released by caller */ 400 + ns = aa_get_namespace(root); 401 + goto out; 402 + } 403 + 404 + /* try and find the specified ns and if it doesn't exist create it */ 405 + /* released by caller */ 406 + ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name)); 407 + if (!ns) { 408 + /* namespace not found */ 409 + struct aa_namespace *new_ns; 410 + write_unlock(&root->lock); 411 + new_ns = alloc_namespace(root->base.hname, name); 412 + if (!new_ns) 413 + return NULL; 414 + write_lock(&root->lock); 415 + /* test for race when new_ns was allocated */ 416 + ns = __aa_find_namespace(&root->sub_ns, name); 417 + if (!ns) { 418 + /* add parent ref */ 419 + new_ns->parent = aa_get_namespace(root); 420 + 421 + list_add(&new_ns->base.list, &root->sub_ns); 422 + /* add list ref */ 423 + ns = aa_get_namespace(new_ns); 424 + } else { 425 + /* raced so free the new one */ 426 + free_namespace(new_ns); 427 + /* get reference on namespace */ 428 + aa_get_namespace(ns); 429 + } 430 + } 431 + out: 432 + write_unlock(&root->lock); 433 + 434 + /* return ref */ 435 + return ns; 436 + } 437 + 438 + /** 439 + * __list_add_profile - add a profile to a list 440 + * @list: list to add it to (NOT NULL) 441 + * @profile: the profile to add (NOT NULL) 442 + * 443 + * refcount @profile, should be put by __list_remove_profile 444 + * 445 + * Requires: namespace lock be held, or list not be shared 446 + */ 447 + static void __list_add_profile(struct list_head *list, 448 + struct aa_profile *profile) 449 + { 450 + list_add(&profile->base.list, list); 451 + /* get list reference */ 452 + aa_get_profile(profile); 453 + } 454 + 455 + /** 456 + * __list_remove_profile - remove a profile from the list it is on 457 + * @profile: the profile to remove (NOT NULL) 458 + * 459 + * remove a profile from the list, warning generally removal should 460 + * be done with __replace_profile as most profile removals are 461 + * replacements to the unconfined profile. 462 + * 463 + * put @profile list refcount 464 + * 465 + * Requires: namespace lock be held, or list not have been live 466 + */ 467 + static void __list_remove_profile(struct aa_profile *profile) 468 + { 469 + list_del_init(&profile->base.list); 470 + if (!(profile->flags & PFLAG_NO_LIST_REF)) 471 + /* release list reference */ 472 + aa_put_profile(profile); 473 + } 474 + 475 + /** 476 + * __replace_profile - replace @old with @new on a list 477 + * @old: profile to be replaced (NOT NULL) 478 + * @new: profile to replace @old with (NOT NULL) 479 + * 480 + * Will duplicate and refcount elements that @new inherits from @old 481 + * and will inherit @old children. 482 + * 483 + * refcount @new for list, put @old list refcount 484 + * 485 + * Requires: namespace list lock be held, or list not be shared 486 + */ 487 + static void __replace_profile(struct aa_profile *old, struct aa_profile *new) 488 + { 489 + struct aa_policy *policy; 490 + struct aa_profile *child, *tmp; 491 + 492 + if (old->parent) 493 + policy = &old->parent->base; 494 + else 495 + policy = &old->ns->base; 496 + 497 + /* released when @new is freed */ 498 + new->parent = aa_get_profile(old->parent); 499 + new->ns = aa_get_namespace(old->ns); 500 + new->sid = old->sid; 501 + __list_add_profile(&policy->profiles, new); 502 + /* inherit children */ 503 + list_for_each_entry_safe(child, tmp, &old->base.profiles, base.list) { 504 + aa_put_profile(child->parent); 505 + child->parent = aa_get_profile(new); 506 + /* list refcount transferred to @new*/ 507 + list_move(&child->base.list, &new->base.profiles); 508 + } 509 + 510 + /* released by free_profile */ 511 + old->replacedby = aa_get_profile(new); 512 + __list_remove_profile(old); 513 + } 514 + 515 + static void __profile_list_release(struct list_head *head); 516 + 517 + /** 518 + * __remove_profile - remove old profile, and children 519 + * @profile: profile to be replaced (NOT NULL) 520 + * 521 + * Requires: namespace list lock be held, or list not be shared 522 + */ 523 + static void __remove_profile(struct aa_profile *profile) 524 + { 525 + /* release any children lists first */ 526 + __profile_list_release(&profile->base.profiles); 527 + /* released by free_profile */ 528 + profile->replacedby = aa_get_profile(profile->ns->unconfined); 529 + __list_remove_profile(profile); 530 + } 531 + 532 + /** 533 + * __profile_list_release - remove all profiles on the list and put refs 534 + * @head: list of profiles (NOT NULL) 535 + * 536 + * Requires: namespace lock be held 537 + */ 538 + static void __profile_list_release(struct list_head *head) 539 + { 540 + struct aa_profile *profile, *tmp; 541 + list_for_each_entry_safe(profile, tmp, head, base.list) 542 + __remove_profile(profile); 543 + } 544 + 545 + static void __ns_list_release(struct list_head *head); 546 + 547 + /** 548 + * destroy_namespace - remove everything contained by @ns 549 + * @ns: namespace to have it contents removed (NOT NULL) 550 + */ 551 + static void destroy_namespace(struct aa_namespace *ns) 552 + { 553 + if (!ns) 554 + return; 555 + 556 + write_lock(&ns->lock); 557 + /* release all profiles in this namespace */ 558 + __profile_list_release(&ns->base.profiles); 559 + 560 + /* release all sub namespaces */ 561 + __ns_list_release(&ns->sub_ns); 562 + 563 + write_unlock(&ns->lock); 564 + } 565 + 566 + /** 567 + * __remove_namespace - remove a namespace and all its children 568 + * @ns: namespace to be removed (NOT NULL) 569 + * 570 + * Requires: ns->parent->lock be held and ns removed from parent. 571 + */ 572 + static void __remove_namespace(struct aa_namespace *ns) 573 + { 574 + struct aa_profile *unconfined = ns->unconfined; 575 + 576 + /* remove ns from namespace list */ 577 + list_del_init(&ns->base.list); 578 + 579 + /* 580 + * break the ns, unconfined profile cyclic reference and forward 581 + * all new unconfined profiles requests to the parent namespace 582 + * This will result in all confined tasks that have a profile 583 + * being removed, inheriting the parent->unconfined profile. 584 + */ 585 + if (ns->parent) 586 + ns->unconfined = aa_get_profile(ns->parent->unconfined); 587 + 588 + destroy_namespace(ns); 589 + 590 + /* release original ns->unconfined ref */ 591 + aa_put_profile(unconfined); 592 + /* release ns->base.list ref, from removal above */ 593 + aa_put_namespace(ns); 594 + } 595 + 596 + /** 597 + * __ns_list_release - remove all profile namespaces on the list put refs 598 + * @head: list of profile namespaces (NOT NULL) 599 + * 600 + * Requires: namespace lock be held 601 + */ 602 + static void __ns_list_release(struct list_head *head) 603 + { 604 + struct aa_namespace *ns, *tmp; 605 + list_for_each_entry_safe(ns, tmp, head, base.list) 606 + __remove_namespace(ns); 607 + 608 + } 609 + 610 + /** 611 + * aa_alloc_root_ns - allocate the root profile namespace 612 + * 613 + * Returns: %0 on success else error 614 + * 615 + */ 616 + int __init aa_alloc_root_ns(void) 617 + { 618 + /* released by aa_free_root_ns - used as list ref*/ 619 + root_ns = alloc_namespace(NULL, "root"); 620 + if (!root_ns) 621 + return -ENOMEM; 622 + 623 + return 0; 624 + } 625 + 626 + /** 627 + * aa_free_root_ns - free the root profile namespace 628 + */ 629 + void __init aa_free_root_ns(void) 630 + { 631 + struct aa_namespace *ns = root_ns; 632 + root_ns = NULL; 633 + 634 + destroy_namespace(ns); 635 + aa_put_namespace(ns); 636 + } 637 + 638 + /** 639 + * aa_alloc_profile - allocate, initialize and return a new profile 640 + * @hname: name of the profile (NOT NULL) 641 + * 642 + * Returns: refcount profile or NULL on failure 643 + */ 644 + struct aa_profile *aa_alloc_profile(const char *hname) 645 + { 646 + struct aa_profile *profile; 647 + 648 + /* freed by free_profile - usually through aa_put_profile */ 649 + profile = kzalloc(sizeof(*profile), GFP_KERNEL); 650 + if (!profile) 651 + return NULL; 652 + 653 + if (!policy_init(&profile->base, NULL, hname)) { 654 + kzfree(profile); 655 + return NULL; 656 + } 657 + 658 + /* refcount released by caller */ 659 + return profile; 660 + } 661 + 662 + /** 663 + * aa_new_null_profile - create a new null-X learning profile 664 + * @parent: profile that caused this profile to be created (NOT NULL) 665 + * @hat: true if the null- learning profile is a hat 666 + * 667 + * Create a null- complain mode profile used in learning mode. The name of 668 + * the profile is unique and follows the format of parent//null-sid. 669 + * 670 + * null profiles are added to the profile list but the list does not 671 + * hold a count on them so that they are automatically released when 672 + * not in use. 673 + * 674 + * Returns: new refcounted profile else NULL on failure 675 + */ 676 + struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat) 677 + { 678 + struct aa_profile *profile = NULL; 679 + char *name; 680 + u32 sid = aa_alloc_sid(); 681 + 682 + /* freed below */ 683 + name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, GFP_KERNEL); 684 + if (!name) 685 + goto fail; 686 + sprintf(name, "%s//null-%x", parent->base.hname, sid); 687 + 688 + profile = aa_alloc_profile(name); 689 + kfree(name); 690 + if (!profile) 691 + goto fail; 692 + 693 + profile->sid = sid; 694 + profile->mode = APPARMOR_COMPLAIN; 695 + profile->flags = PFLAG_NULL; 696 + if (hat) 697 + profile->flags |= PFLAG_HAT; 698 + 699 + /* released on free_profile */ 700 + profile->parent = aa_get_profile(parent); 701 + profile->ns = aa_get_namespace(parent->ns); 702 + 703 + write_lock(&profile->ns->lock); 704 + __list_add_profile(&parent->base.profiles, profile); 705 + write_unlock(&profile->ns->lock); 706 + 707 + /* refcount released by caller */ 708 + return profile; 709 + 710 + fail: 711 + aa_free_sid(sid); 712 + return NULL; 713 + } 714 + 715 + /** 716 + * free_profile - free a profile 717 + * @profile: the profile to free (MAYBE NULL) 718 + * 719 + * Free a profile, its hats and null_profile. All references to the profile, 720 + * its hats and null_profile must have been put. 721 + * 722 + * If the profile was referenced from a task context, free_profile() will 723 + * be called from an rcu callback routine, so we must not sleep here. 724 + */ 725 + static void free_profile(struct aa_profile *profile) 726 + { 727 + AA_DEBUG("%s(%p)\n", __func__, profile); 728 + 729 + if (!profile) 730 + return; 731 + 732 + if (!list_empty(&profile->base.list)) { 733 + AA_ERROR("%s: internal error, " 734 + "profile '%s' still on ns list\n", 735 + __func__, profile->base.name); 736 + BUG(); 737 + } 738 + 739 + /* free children profiles */ 740 + policy_destroy(&profile->base); 741 + aa_put_profile(profile->parent); 742 + 743 + aa_put_namespace(profile->ns); 744 + kzfree(profile->rename); 745 + 746 + aa_free_file_rules(&profile->file); 747 + aa_free_cap_rules(&profile->caps); 748 + aa_free_rlimit_rules(&profile->rlimits); 749 + 750 + aa_free_sid(profile->sid); 751 + aa_put_dfa(profile->xmatch); 752 + 753 + aa_put_profile(profile->replacedby); 754 + 755 + kzfree(profile); 756 + } 757 + 758 + /** 759 + * aa_free_profile_kref - free aa_profile by kref (called by aa_put_profile) 760 + * @kr: kref callback for freeing of a profile (NOT NULL) 761 + */ 762 + void aa_free_profile_kref(struct kref *kref) 763 + { 764 + struct aa_profile *p = container_of(kref, struct aa_profile, 765 + base.count); 766 + 767 + free_profile(p); 768 + } 769 + 770 + /* TODO: profile accounting - setup in remove */ 771 + 772 + /** 773 + * __find_child - find a profile on @head list with a name matching @name 774 + * @head: list to search (NOT NULL) 775 + * @name: name of profile (NOT NULL) 776 + * 777 + * Requires: ns lock protecting list be held 778 + * 779 + * Returns: unrefcounted profile ptr, or NULL if not found 780 + */ 781 + static struct aa_profile *__find_child(struct list_head *head, const char *name) 782 + { 783 + return (struct aa_profile *)__policy_find(head, name); 784 + } 785 + 786 + /** 787 + * __strn_find_child - find a profile on @head list using substring of @name 788 + * @head: list to search (NOT NULL) 789 + * @name: name of profile (NOT NULL) 790 + * @len: length of @name substring to match 791 + * 792 + * Requires: ns lock protecting list be held 793 + * 794 + * Returns: unrefcounted profile ptr, or NULL if not found 795 + */ 796 + static struct aa_profile *__strn_find_child(struct list_head *head, 797 + const char *name, int len) 798 + { 799 + return (struct aa_profile *)__policy_strn_find(head, name, len); 800 + } 801 + 802 + /** 803 + * aa_find_child - find a profile by @name in @parent 804 + * @parent: profile to search (NOT NULL) 805 + * @name: profile name to search for (NOT NULL) 806 + * 807 + * Returns: a refcounted profile or NULL if not found 808 + */ 809 + struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name) 810 + { 811 + struct aa_profile *profile; 812 + 813 + read_lock(&parent->ns->lock); 814 + profile = aa_get_profile(__find_child(&parent->base.profiles, name)); 815 + read_unlock(&parent->ns->lock); 816 + 817 + /* refcount released by caller */ 818 + return profile; 819 + } 820 + 821 + /** 822 + * __lookup_parent - lookup the parent of a profile of name @hname 823 + * @ns: namespace to lookup profile in (NOT NULL) 824 + * @hname: hierarchical profile name to find parent of (NOT NULL) 825 + * 826 + * Lookups up the parent of a fully qualified profile name, the profile 827 + * that matches hname does not need to exist, in general this 828 + * is used to load a new profile. 829 + * 830 + * Requires: ns->lock be held 831 + * 832 + * Returns: unrefcounted policy or NULL if not found 833 + */ 834 + static struct aa_policy *__lookup_parent(struct aa_namespace *ns, 835 + const char *hname) 836 + { 837 + struct aa_policy *policy; 838 + struct aa_profile *profile = NULL; 839 + char *split; 840 + 841 + policy = &ns->base; 842 + 843 + for (split = strstr(hname, "//"); split;) { 844 + profile = __strn_find_child(&policy->profiles, hname, 845 + split - hname); 846 + if (!profile) 847 + return NULL; 848 + policy = &profile->base; 849 + hname = split + 2; 850 + split = strstr(hname, "//"); 851 + } 852 + if (!profile) 853 + return &ns->base; 854 + return &profile->base; 855 + } 856 + 857 + /** 858 + * __lookup_profile - lookup the profile matching @hname 859 + * @base: base list to start looking up profile name from (NOT NULL) 860 + * @hname: hierarchical profile name (NOT NULL) 861 + * 862 + * Requires: ns->lock be held 863 + * 864 + * Returns: unrefcounted profile pointer or NULL if not found 865 + * 866 + * Do a relative name lookup, recursing through profile tree. 867 + */ 868 + static struct aa_profile *__lookup_profile(struct aa_policy *base, 869 + const char *hname) 870 + { 871 + struct aa_profile *profile = NULL; 872 + char *split; 873 + 874 + for (split = strstr(hname, "//"); split;) { 875 + profile = __strn_find_child(&base->profiles, hname, 876 + split - hname); 877 + if (!profile) 878 + return NULL; 879 + 880 + base = &profile->base; 881 + hname = split + 2; 882 + split = strstr(hname, "//"); 883 + } 884 + 885 + profile = __find_child(&base->profiles, hname); 886 + 887 + return profile; 888 + } 889 + 890 + /** 891 + * aa_lookup_profile - find a profile by its full or partial name 892 + * @ns: the namespace to start from (NOT NULL) 893 + * @hname: name to do lookup on. Does not contain namespace prefix (NOT NULL) 894 + * 895 + * Returns: refcounted profile or NULL if not found 896 + */ 897 + struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *hname) 898 + { 899 + struct aa_profile *profile; 900 + 901 + read_lock(&ns->lock); 902 + profile = aa_get_profile(__lookup_profile(&ns->base, hname)); 903 + read_unlock(&ns->lock); 904 + 905 + /* refcount released by caller */ 906 + return profile; 907 + } 908 + 909 + /** 910 + * replacement_allowed - test to see if replacement is allowed 911 + * @profile: profile to test if it can be replaced (MAYBE NULL) 912 + * @noreplace: true if replacement shouldn't be allowed but addition is okay 913 + * @info: Returns - info about why replacement failed (NOT NULL) 914 + * 915 + * Returns: %0 if replacement allowed else error code 916 + */ 917 + static int replacement_allowed(struct aa_profile *profile, int noreplace, 918 + const char **info) 919 + { 920 + if (profile) { 921 + if (profile->flags & PFLAG_IMMUTABLE) { 922 + *info = "cannot replace immutible profile"; 923 + return -EPERM; 924 + } else if (noreplace) { 925 + *info = "profile already exists"; 926 + return -EEXIST; 927 + } 928 + } 929 + return 0; 930 + } 931 + 932 + /** 933 + * __add_new_profile - simple wrapper around __list_add_profile 934 + * @ns: namespace that profile is being added to (NOT NULL) 935 + * @policy: the policy container to add the profile to (NOT NULL) 936 + * @profile: profile to add (NOT NULL) 937 + * 938 + * add a profile to a list and do other required basic allocations 939 + */ 940 + static void __add_new_profile(struct aa_namespace *ns, struct aa_policy *policy, 941 + struct aa_profile *profile) 942 + { 943 + if (policy != &ns->base) 944 + /* released on profile replacement or free_profile */ 945 + profile->parent = aa_get_profile((struct aa_profile *) policy); 946 + __list_add_profile(&policy->profiles, profile); 947 + /* released on free_profile */ 948 + profile->sid = aa_alloc_sid(); 949 + profile->ns = aa_get_namespace(ns); 950 + } 951 + 952 + /** 953 + * aa_audit_policy - Do auditing of policy changes 954 + * @op: policy operation being performed 955 + * @gfp: memory allocation flags 956 + * @name: name of profile being manipulated (NOT NULL) 957 + * @info: any extra information to be audited (MAYBE NULL) 958 + * @error: error code 959 + * 960 + * Returns: the error to be returned after audit is done 961 + */ 962 + static int audit_policy(int op, gfp_t gfp, const char *name, const char *info, 963 + int error) 964 + { 965 + struct common_audit_data sa; 966 + COMMON_AUDIT_DATA_INIT(&sa, NONE); 967 + sa.aad.op = op; 968 + sa.aad.name = name; 969 + sa.aad.info = info; 970 + sa.aad.error = error; 971 + 972 + return aa_audit(AUDIT_APPARMOR_STATUS, __aa_current_profile(), gfp, 973 + &sa, NULL); 974 + } 975 + 976 + /** 977 + * aa_may_manage_policy - can the current task manage policy 978 + * @op: the policy manipulation operation being done 979 + * 980 + * Returns: true if the task is allowed to manipulate policy 981 + */ 982 + bool aa_may_manage_policy(int op) 983 + { 984 + /* check if loading policy is locked out */ 985 + if (aa_g_lock_policy) { 986 + audit_policy(op, GFP_KERNEL, NULL, "policy_locked", -EACCES); 987 + return 0; 988 + } 989 + 990 + if (!capable(CAP_MAC_ADMIN)) { 991 + audit_policy(op, GFP_KERNEL, NULL, "not policy admin", -EACCES); 992 + return 0; 993 + } 994 + 995 + return 1; 996 + } 997 + 998 + /** 999 + * aa_replace_profiles - replace profile(s) on the profile list 1000 + * @udata: serialized data stream (NOT NULL) 1001 + * @size: size of the serialized data stream 1002 + * @noreplace: true if only doing addition, no replacement allowed 1003 + * 1004 + * unpack and replace a profile on the profile list and uses of that profile 1005 + * by any aa_task_cxt. If the profile does not exist on the profile list 1006 + * it is added. 1007 + * 1008 + * Returns: size of data consumed else error code on failure. 1009 + */ 1010 + ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace) 1011 + { 1012 + struct aa_policy *policy; 1013 + struct aa_profile *old_profile = NULL, *new_profile = NULL; 1014 + struct aa_profile *rename_profile = NULL; 1015 + struct aa_namespace *ns = NULL; 1016 + const char *ns_name, *name = NULL, *info = NULL; 1017 + int op = OP_PROF_REPL; 1018 + ssize_t error; 1019 + 1020 + /* released below */ 1021 + new_profile = aa_unpack(udata, size, &ns_name); 1022 + if (IS_ERR(new_profile)) { 1023 + error = PTR_ERR(new_profile); 1024 + new_profile = NULL; 1025 + goto fail; 1026 + } 1027 + 1028 + /* released below */ 1029 + ns = aa_prepare_namespace(ns_name); 1030 + if (!ns) { 1031 + info = "failed to prepare namespace"; 1032 + error = -ENOMEM; 1033 + name = ns_name; 1034 + goto fail; 1035 + } 1036 + 1037 + name = new_profile->base.hname; 1038 + 1039 + write_lock(&ns->lock); 1040 + /* no ref on policy only use inside lock */ 1041 + policy = __lookup_parent(ns, new_profile->base.hname); 1042 + 1043 + if (!policy) { 1044 + info = "parent does not exist"; 1045 + error = -ENOENT; 1046 + goto audit; 1047 + } 1048 + 1049 + old_profile = __find_child(&policy->profiles, new_profile->base.name); 1050 + /* released below */ 1051 + aa_get_profile(old_profile); 1052 + 1053 + if (new_profile->rename) { 1054 + rename_profile = __lookup_profile(&ns->base, 1055 + new_profile->rename); 1056 + /* released below */ 1057 + aa_get_profile(rename_profile); 1058 + 1059 + if (!rename_profile) { 1060 + info = "profile to rename does not exist"; 1061 + name = new_profile->rename; 1062 + error = -ENOENT; 1063 + goto audit; 1064 + } 1065 + } 1066 + 1067 + error = replacement_allowed(old_profile, noreplace, &info); 1068 + if (error) 1069 + goto audit; 1070 + 1071 + error = replacement_allowed(rename_profile, noreplace, &info); 1072 + if (error) 1073 + goto audit; 1074 + 1075 + audit: 1076 + if (!old_profile && !rename_profile) 1077 + op = OP_PROF_LOAD; 1078 + 1079 + error = audit_policy(op, GFP_ATOMIC, name, info, error); 1080 + 1081 + if (!error) { 1082 + if (rename_profile) 1083 + __replace_profile(rename_profile, new_profile); 1084 + if (old_profile) { 1085 + /* when there are both rename and old profiles 1086 + * inherit old profiles sid 1087 + */ 1088 + if (rename_profile) 1089 + aa_free_sid(new_profile->sid); 1090 + __replace_profile(old_profile, new_profile); 1091 + } 1092 + if (!(old_profile || rename_profile)) 1093 + __add_new_profile(ns, policy, new_profile); 1094 + } 1095 + write_unlock(&ns->lock); 1096 + 1097 + out: 1098 + aa_put_namespace(ns); 1099 + aa_put_profile(rename_profile); 1100 + aa_put_profile(old_profile); 1101 + aa_put_profile(new_profile); 1102 + if (error) 1103 + return error; 1104 + return size; 1105 + 1106 + fail: 1107 + error = audit_policy(op, GFP_KERNEL, name, info, error); 1108 + goto out; 1109 + } 1110 + 1111 + /** 1112 + * aa_remove_profiles - remove profile(s) from the system 1113 + * @fqname: name of the profile or namespace to remove (NOT NULL) 1114 + * @size: size of the name 1115 + * 1116 + * Remove a profile or sub namespace from the current namespace, so that 1117 + * they can not be found anymore and mark them as replaced by unconfined 1118 + * 1119 + * NOTE: removing confinement does not restore rlimits to preconfinemnet values 1120 + * 1121 + * Returns: size of data consume else error code if fails 1122 + */ 1123 + ssize_t aa_remove_profiles(char *fqname, size_t size) 1124 + { 1125 + struct aa_namespace *root, *ns = NULL; 1126 + struct aa_profile *profile = NULL; 1127 + const char *name = fqname, *info = NULL; 1128 + ssize_t error = 0; 1129 + 1130 + if (*fqname == 0) { 1131 + info = "no profile specified"; 1132 + error = -ENOENT; 1133 + goto fail; 1134 + } 1135 + 1136 + root = aa_current_profile()->ns; 1137 + 1138 + if (fqname[0] == ':') { 1139 + char *ns_name; 1140 + name = aa_split_fqname(fqname, &ns_name); 1141 + if (ns_name) { 1142 + /* released below */ 1143 + ns = aa_find_namespace(root, ns_name); 1144 + if (!ns) { 1145 + info = "namespace does not exist"; 1146 + error = -ENOENT; 1147 + goto fail; 1148 + } 1149 + } 1150 + } else 1151 + /* released below */ 1152 + ns = aa_get_namespace(root); 1153 + 1154 + write_lock(&ns->lock); 1155 + if (!name) { 1156 + /* remove namespace - can only happen if fqname[0] == ':' */ 1157 + __remove_namespace(ns); 1158 + } else { 1159 + /* remove profile */ 1160 + profile = aa_get_profile(__lookup_profile(&ns->base, name)); 1161 + if (!profile) { 1162 + error = -ENOENT; 1163 + info = "profile does not exist"; 1164 + goto fail_ns_lock; 1165 + } 1166 + name = profile->base.hname; 1167 + __remove_profile(profile); 1168 + } 1169 + write_unlock(&ns->lock); 1170 + 1171 + /* don't fail removal if audit fails */ 1172 + (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error); 1173 + aa_put_namespace(ns); 1174 + aa_put_profile(profile); 1175 + return size; 1176 + 1177 + fail_ns_lock: 1178 + write_unlock(&ns->lock); 1179 + aa_put_namespace(ns); 1180 + 1181 + fail: 1182 + (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error); 1183 + return error; 1184 + }
+703
security/apparmor/policy_unpack.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor functions for unpacking policy loaded from 5 + * userspace. 6 + * 7 + * Copyright (C) 1998-2008 Novell/SUSE 8 + * Copyright 2009-2010 Canonical Ltd. 9 + * 10 + * This program is free software; you can redistribute it and/or 11 + * modify it under the terms of the GNU General Public License as 12 + * published by the Free Software Foundation, version 2 of the 13 + * License. 14 + * 15 + * AppArmor uses a serialized binary format for loading policy. 16 + * To find policy format documentation look in Documentation/apparmor.txt 17 + * All policy is validated before it is used. 18 + */ 19 + 20 + #include <asm/unaligned.h> 21 + #include <linux/ctype.h> 22 + #include <linux/errno.h> 23 + 24 + #include "include/apparmor.h" 25 + #include "include/audit.h" 26 + #include "include/context.h" 27 + #include "include/match.h" 28 + #include "include/policy.h" 29 + #include "include/policy_unpack.h" 30 + #include "include/sid.h" 31 + 32 + /* 33 + * The AppArmor interface treats data as a type byte followed by the 34 + * actual data. The interface has the notion of a a named entry 35 + * which has a name (AA_NAME typecode followed by name string) followed by 36 + * the entries typecode and data. Named types allow for optional 37 + * elements and extensions to be added and tested for without breaking 38 + * backwards compatibility. 39 + */ 40 + 41 + enum aa_code { 42 + AA_U8, 43 + AA_U16, 44 + AA_U32, 45 + AA_U64, 46 + AA_NAME, /* same as string except it is items name */ 47 + AA_STRING, 48 + AA_BLOB, 49 + AA_STRUCT, 50 + AA_STRUCTEND, 51 + AA_LIST, 52 + AA_LISTEND, 53 + AA_ARRAY, 54 + AA_ARRAYEND, 55 + }; 56 + 57 + /* 58 + * aa_ext is the read of the buffer containing the serialized profile. The 59 + * data is copied into a kernel buffer in apparmorfs and then handed off to 60 + * the unpack routines. 61 + */ 62 + struct aa_ext { 63 + void *start; 64 + void *end; 65 + void *pos; /* pointer to current position in the buffer */ 66 + u32 version; 67 + }; 68 + 69 + /* audit callback for unpack fields */ 70 + static void audit_cb(struct audit_buffer *ab, void *va) 71 + { 72 + struct common_audit_data *sa = va; 73 + if (sa->aad.iface.target) { 74 + struct aa_profile *name = sa->aad.iface.target; 75 + audit_log_format(ab, " name="); 76 + audit_log_untrustedstring(ab, name->base.hname); 77 + } 78 + if (sa->aad.iface.pos) 79 + audit_log_format(ab, " offset=%ld", sa->aad.iface.pos); 80 + } 81 + 82 + /** 83 + * audit_iface - do audit message for policy unpacking/load/replace/remove 84 + * @new: profile if it has been allocated (MAYBE NULL) 85 + * @name: name of the profile being manipulated (MAYBE NULL) 86 + * @info: any extra info about the failure (MAYBE NULL) 87 + * @e: buffer position info (NOT NULL) 88 + * @error: error code 89 + * 90 + * Returns: %0 or error 91 + */ 92 + static int audit_iface(struct aa_profile *new, const char *name, 93 + const char *info, struct aa_ext *e, int error) 94 + { 95 + struct aa_profile *profile = __aa_current_profile(); 96 + struct common_audit_data sa; 97 + COMMON_AUDIT_DATA_INIT(&sa, NONE); 98 + sa.aad.iface.pos = e->pos - e->start; 99 + sa.aad.iface.target = new; 100 + sa.aad.name = name; 101 + sa.aad.info = info; 102 + sa.aad.error = error; 103 + 104 + return aa_audit(AUDIT_APPARMOR_STATUS, profile, GFP_KERNEL, &sa, 105 + audit_cb); 106 + } 107 + 108 + /* test if read will be in packed data bounds */ 109 + static bool inbounds(struct aa_ext *e, size_t size) 110 + { 111 + return (size <= e->end - e->pos); 112 + } 113 + 114 + /** 115 + * aa_u16_chunck - test and do bounds checking for a u16 size based chunk 116 + * @e: serialized data read head (NOT NULL) 117 + * @chunk: start address for chunk of data (NOT NULL) 118 + * 119 + * Returns: the size of chunk found with the read head at the end of the chunk. 120 + */ 121 + static size_t unpack_u16_chunk(struct aa_ext *e, char **chunk) 122 + { 123 + size_t size = 0; 124 + 125 + if (!inbounds(e, sizeof(u16))) 126 + return 0; 127 + size = le16_to_cpu(get_unaligned((u16 *) e->pos)); 128 + e->pos += sizeof(u16); 129 + if (!inbounds(e, size)) 130 + return 0; 131 + *chunk = e->pos; 132 + e->pos += size; 133 + return size; 134 + } 135 + 136 + /* unpack control byte */ 137 + static bool unpack_X(struct aa_ext *e, enum aa_code code) 138 + { 139 + if (!inbounds(e, 1)) 140 + return 0; 141 + if (*(u8 *) e->pos != code) 142 + return 0; 143 + e->pos++; 144 + return 1; 145 + } 146 + 147 + /** 148 + * unpack_nameX - check is the next element is of type X with a name of @name 149 + * @e: serialized data extent information (NOT NULL) 150 + * @code: type code 151 + * @name: name to match to the serialized element. (MAYBE NULL) 152 + * 153 + * check that the next serialized data element is of type X and has a tag 154 + * name @name. If @name is specified then there must be a matching 155 + * name element in the stream. If @name is NULL any name element will be 156 + * skipped and only the typecode will be tested. 157 + * 158 + * Returns 1 on success (both type code and name tests match) and the read 159 + * head is advanced past the headers 160 + * 161 + * Returns: 0 if either match fails, the read head does not move 162 + */ 163 + static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name) 164 + { 165 + /* 166 + * May need to reset pos if name or type doesn't match 167 + */ 168 + void *pos = e->pos; 169 + /* 170 + * Check for presence of a tagname, and if present name size 171 + * AA_NAME tag value is a u16. 172 + */ 173 + if (unpack_X(e, AA_NAME)) { 174 + char *tag = NULL; 175 + size_t size = unpack_u16_chunk(e, &tag); 176 + /* if a name is specified it must match. otherwise skip tag */ 177 + if (name && (!size || strcmp(name, tag))) 178 + goto fail; 179 + } else if (name) { 180 + /* if a name is specified and there is no name tag fail */ 181 + goto fail; 182 + } 183 + 184 + /* now check if type code matches */ 185 + if (unpack_X(e, code)) 186 + return 1; 187 + 188 + fail: 189 + e->pos = pos; 190 + return 0; 191 + } 192 + 193 + static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) 194 + { 195 + if (unpack_nameX(e, AA_U32, name)) { 196 + if (!inbounds(e, sizeof(u32))) 197 + return 0; 198 + if (data) 199 + *data = le32_to_cpu(get_unaligned((u32 *) e->pos)); 200 + e->pos += sizeof(u32); 201 + return 1; 202 + } 203 + return 0; 204 + } 205 + 206 + static bool unpack_u64(struct aa_ext *e, u64 *data, const char *name) 207 + { 208 + if (unpack_nameX(e, AA_U64, name)) { 209 + if (!inbounds(e, sizeof(u64))) 210 + return 0; 211 + if (data) 212 + *data = le64_to_cpu(get_unaligned((u64 *) e->pos)); 213 + e->pos += sizeof(u64); 214 + return 1; 215 + } 216 + return 0; 217 + } 218 + 219 + static size_t unpack_array(struct aa_ext *e, const char *name) 220 + { 221 + if (unpack_nameX(e, AA_ARRAY, name)) { 222 + int size; 223 + if (!inbounds(e, sizeof(u16))) 224 + return 0; 225 + size = (int)le16_to_cpu(get_unaligned((u16 *) e->pos)); 226 + e->pos += sizeof(u16); 227 + return size; 228 + } 229 + return 0; 230 + } 231 + 232 + static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name) 233 + { 234 + if (unpack_nameX(e, AA_BLOB, name)) { 235 + u32 size; 236 + if (!inbounds(e, sizeof(u32))) 237 + return 0; 238 + size = le32_to_cpu(get_unaligned((u32 *) e->pos)); 239 + e->pos += sizeof(u32); 240 + if (inbounds(e, (size_t) size)) { 241 + *blob = e->pos; 242 + e->pos += size; 243 + return size; 244 + } 245 + } 246 + return 0; 247 + } 248 + 249 + static int unpack_str(struct aa_ext *e, const char **string, const char *name) 250 + { 251 + char *src_str; 252 + size_t size = 0; 253 + void *pos = e->pos; 254 + *string = NULL; 255 + if (unpack_nameX(e, AA_STRING, name)) { 256 + size = unpack_u16_chunk(e, &src_str); 257 + if (size) { 258 + /* strings are null terminated, length is size - 1 */ 259 + if (src_str[size - 1] != 0) 260 + goto fail; 261 + *string = src_str; 262 + } 263 + } 264 + return size; 265 + 266 + fail: 267 + e->pos = pos; 268 + return 0; 269 + } 270 + 271 + static int unpack_strdup(struct aa_ext *e, char **string, const char *name) 272 + { 273 + const char *tmp; 274 + void *pos = e->pos; 275 + int res = unpack_str(e, &tmp, name); 276 + *string = NULL; 277 + 278 + if (!res) 279 + return 0; 280 + 281 + *string = kmemdup(tmp, res, GFP_KERNEL); 282 + if (!*string) { 283 + e->pos = pos; 284 + return 0; 285 + } 286 + 287 + return res; 288 + } 289 + 290 + /** 291 + * verify_accept - verify the accept tables of a dfa 292 + * @dfa: dfa to verify accept tables of (NOT NULL) 293 + * @flags: flags governing dfa 294 + * 295 + * Returns: 1 if valid accept tables else 0 if error 296 + */ 297 + static bool verify_accept(struct aa_dfa *dfa, int flags) 298 + { 299 + int i; 300 + 301 + /* verify accept permissions */ 302 + for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) { 303 + int mode = ACCEPT_TABLE(dfa)[i]; 304 + 305 + if (mode & ~DFA_VALID_PERM_MASK) 306 + return 0; 307 + 308 + if (ACCEPT_TABLE2(dfa)[i] & ~DFA_VALID_PERM2_MASK) 309 + return 0; 310 + } 311 + return 1; 312 + } 313 + 314 + /** 315 + * unpack_dfa - unpack a file rule dfa 316 + * @e: serialized data extent information (NOT NULL) 317 + * 318 + * returns dfa or ERR_PTR or NULL if no dfa 319 + */ 320 + static struct aa_dfa *unpack_dfa(struct aa_ext *e) 321 + { 322 + char *blob = NULL; 323 + size_t size; 324 + struct aa_dfa *dfa = NULL; 325 + 326 + size = unpack_blob(e, &blob, "aadfa"); 327 + if (size) { 328 + /* 329 + * The dfa is aligned with in the blob to 8 bytes 330 + * from the beginning of the stream. 331 + */ 332 + size_t sz = blob - (char *)e->start; 333 + size_t pad = ALIGN(sz, 8) - sz; 334 + int flags = TO_ACCEPT1_FLAG(YYTD_DATA32) | 335 + TO_ACCEPT2_FLAG(YYTD_DATA32); 336 + 337 + 338 + if (aa_g_paranoid_load) 339 + flags |= DFA_FLAG_VERIFY_STATES; 340 + 341 + dfa = aa_dfa_unpack(blob + pad, size - pad, flags); 342 + 343 + if (IS_ERR(dfa)) 344 + return dfa; 345 + 346 + if (!verify_accept(dfa, flags)) 347 + goto fail; 348 + } 349 + 350 + return dfa; 351 + 352 + fail: 353 + aa_put_dfa(dfa); 354 + return ERR_PTR(-EPROTO); 355 + } 356 + 357 + /** 358 + * unpack_trans_table - unpack a profile transition table 359 + * @e: serialized data extent information (NOT NULL) 360 + * @profile: profile to add the accept table to (NOT NULL) 361 + * 362 + * Returns: 1 if table succesfully unpacked 363 + */ 364 + static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile) 365 + { 366 + void *pos = e->pos; 367 + 368 + /* exec table is optional */ 369 + if (unpack_nameX(e, AA_STRUCT, "xtable")) { 370 + int i, size; 371 + 372 + size = unpack_array(e, NULL); 373 + /* currently 4 exec bits and entries 0-3 are reserved iupcx */ 374 + if (size > 16 - 4) 375 + goto fail; 376 + profile->file.trans.table = kzalloc(sizeof(char *) * size, 377 + GFP_KERNEL); 378 + if (!profile->file.trans.table) 379 + goto fail; 380 + 381 + profile->file.trans.size = size; 382 + for (i = 0; i < size; i++) { 383 + char *str; 384 + int c, j, size = unpack_strdup(e, &str, NULL); 385 + /* unpack_strdup verifies that the last character is 386 + * null termination byte. 387 + */ 388 + if (!size) 389 + goto fail; 390 + profile->file.trans.table[i] = str; 391 + /* verify that name doesn't start with space */ 392 + if (isspace(*str)) 393 + goto fail; 394 + 395 + /* count internal # of internal \0 */ 396 + for (c = j = 0; j < size - 2; j++) { 397 + if (!str[j]) 398 + c++; 399 + } 400 + if (*str == ':') { 401 + /* beginning with : requires an embedded \0, 402 + * verify that exactly 1 internal \0 exists 403 + * trailing \0 already verified by unpack_strdup 404 + */ 405 + if (c != 1) 406 + goto fail; 407 + /* first character after : must be valid */ 408 + if (!str[1]) 409 + goto fail; 410 + } else if (c) 411 + /* fail - all other cases with embedded \0 */ 412 + goto fail; 413 + } 414 + if (!unpack_nameX(e, AA_ARRAYEND, NULL)) 415 + goto fail; 416 + if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 417 + goto fail; 418 + } 419 + return 1; 420 + 421 + fail: 422 + aa_free_domain_entries(&profile->file.trans); 423 + e->pos = pos; 424 + return 0; 425 + } 426 + 427 + static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile) 428 + { 429 + void *pos = e->pos; 430 + 431 + /* rlimits are optional */ 432 + if (unpack_nameX(e, AA_STRUCT, "rlimits")) { 433 + int i, size; 434 + u32 tmp = 0; 435 + if (!unpack_u32(e, &tmp, NULL)) 436 + goto fail; 437 + profile->rlimits.mask = tmp; 438 + 439 + size = unpack_array(e, NULL); 440 + if (size > RLIM_NLIMITS) 441 + goto fail; 442 + for (i = 0; i < size; i++) { 443 + u64 tmp = 0; 444 + int a = aa_map_resource(i); 445 + if (!unpack_u64(e, &tmp, NULL)) 446 + goto fail; 447 + profile->rlimits.limits[a].rlim_max = tmp; 448 + } 449 + if (!unpack_nameX(e, AA_ARRAYEND, NULL)) 450 + goto fail; 451 + if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 452 + goto fail; 453 + } 454 + return 1; 455 + 456 + fail: 457 + e->pos = pos; 458 + return 0; 459 + } 460 + 461 + /** 462 + * unpack_profile - unpack a serialized profile 463 + * @e: serialized data extent information (NOT NULL) 464 + * 465 + * NOTE: unpack profile sets audit struct if there is a failure 466 + */ 467 + static struct aa_profile *unpack_profile(struct aa_ext *e) 468 + { 469 + struct aa_profile *profile = NULL; 470 + const char *name = NULL; 471 + int error = -EPROTO; 472 + kernel_cap_t tmpcap; 473 + u32 tmp; 474 + 475 + /* check that we have the right struct being passed */ 476 + if (!unpack_nameX(e, AA_STRUCT, "profile")) 477 + goto fail; 478 + if (!unpack_str(e, &name, NULL)) 479 + goto fail; 480 + 481 + profile = aa_alloc_profile(name); 482 + if (!profile) 483 + return ERR_PTR(-ENOMEM); 484 + 485 + /* profile renaming is optional */ 486 + (void) unpack_str(e, &profile->rename, "rename"); 487 + 488 + /* xmatch is optional and may be NULL */ 489 + profile->xmatch = unpack_dfa(e); 490 + if (IS_ERR(profile->xmatch)) { 491 + error = PTR_ERR(profile->xmatch); 492 + profile->xmatch = NULL; 493 + goto fail; 494 + } 495 + /* xmatch_len is not optional if xmatch is set */ 496 + if (profile->xmatch) { 497 + if (!unpack_u32(e, &tmp, NULL)) 498 + goto fail; 499 + profile->xmatch_len = tmp; 500 + } 501 + 502 + /* per profile debug flags (complain, audit) */ 503 + if (!unpack_nameX(e, AA_STRUCT, "flags")) 504 + goto fail; 505 + if (!unpack_u32(e, &tmp, NULL)) 506 + goto fail; 507 + if (tmp) 508 + profile->flags |= PFLAG_HAT; 509 + if (!unpack_u32(e, &tmp, NULL)) 510 + goto fail; 511 + if (tmp) 512 + profile->mode = APPARMOR_COMPLAIN; 513 + if (!unpack_u32(e, &tmp, NULL)) 514 + goto fail; 515 + if (tmp) 516 + profile->audit = AUDIT_ALL; 517 + 518 + if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 519 + goto fail; 520 + 521 + /* path_flags is optional */ 522 + if (unpack_u32(e, &profile->path_flags, "path_flags")) 523 + profile->path_flags |= profile->flags & PFLAG_MEDIATE_DELETED; 524 + else 525 + /* set a default value if path_flags field is not present */ 526 + profile->path_flags = PFLAG_MEDIATE_DELETED; 527 + 528 + if (!unpack_u32(e, &(profile->caps.allow.cap[0]), NULL)) 529 + goto fail; 530 + if (!unpack_u32(e, &(profile->caps.audit.cap[0]), NULL)) 531 + goto fail; 532 + if (!unpack_u32(e, &(profile->caps.quiet.cap[0]), NULL)) 533 + goto fail; 534 + if (!unpack_u32(e, &tmpcap.cap[0], NULL)) 535 + goto fail; 536 + 537 + if (unpack_nameX(e, AA_STRUCT, "caps64")) { 538 + /* optional upper half of 64 bit caps */ 539 + if (!unpack_u32(e, &(profile->caps.allow.cap[1]), NULL)) 540 + goto fail; 541 + if (!unpack_u32(e, &(profile->caps.audit.cap[1]), NULL)) 542 + goto fail; 543 + if (!unpack_u32(e, &(profile->caps.quiet.cap[1]), NULL)) 544 + goto fail; 545 + if (!unpack_u32(e, &(tmpcap.cap[1]), NULL)) 546 + goto fail; 547 + if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 548 + goto fail; 549 + } 550 + 551 + if (unpack_nameX(e, AA_STRUCT, "capsx")) { 552 + /* optional extended caps mediation mask */ 553 + if (!unpack_u32(e, &(profile->caps.extended.cap[0]), NULL)) 554 + goto fail; 555 + if (!unpack_u32(e, &(profile->caps.extended.cap[1]), NULL)) 556 + goto fail; 557 + } 558 + 559 + if (!unpack_rlimits(e, profile)) 560 + goto fail; 561 + 562 + /* get file rules */ 563 + profile->file.dfa = unpack_dfa(e); 564 + if (IS_ERR(profile->file.dfa)) { 565 + error = PTR_ERR(profile->file.dfa); 566 + profile->file.dfa = NULL; 567 + goto fail; 568 + } 569 + 570 + if (!unpack_u32(e, &profile->file.start, "dfa_start")) 571 + /* default start state */ 572 + profile->file.start = DFA_START; 573 + 574 + if (!unpack_trans_table(e, profile)) 575 + goto fail; 576 + 577 + if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 578 + goto fail; 579 + 580 + return profile; 581 + 582 + fail: 583 + if (profile) 584 + name = NULL; 585 + else if (!name) 586 + name = "unknown"; 587 + audit_iface(profile, name, "failed to unpack profile", e, error); 588 + aa_put_profile(profile); 589 + 590 + return ERR_PTR(error); 591 + } 592 + 593 + /** 594 + * verify_head - unpack serialized stream header 595 + * @e: serialized data read head (NOT NULL) 596 + * @ns: Returns - namespace if one is specified else NULL (NOT NULL) 597 + * 598 + * Returns: error or 0 if header is good 599 + */ 600 + static int verify_header(struct aa_ext *e, const char **ns) 601 + { 602 + int error = -EPROTONOSUPPORT; 603 + /* get the interface version */ 604 + if (!unpack_u32(e, &e->version, "version")) { 605 + audit_iface(NULL, NULL, "invalid profile format", e, error); 606 + return error; 607 + } 608 + 609 + /* check that the interface version is currently supported */ 610 + if (e->version != 5) { 611 + audit_iface(NULL, NULL, "unsupported interface version", e, 612 + error); 613 + return error; 614 + } 615 + 616 + /* read the namespace if present */ 617 + if (!unpack_str(e, ns, "namespace")) 618 + *ns = NULL; 619 + 620 + return 0; 621 + } 622 + 623 + static bool verify_xindex(int xindex, int table_size) 624 + { 625 + int index, xtype; 626 + xtype = xindex & AA_X_TYPE_MASK; 627 + index = xindex & AA_X_INDEX_MASK; 628 + if (xtype == AA_X_TABLE && index > table_size) 629 + return 0; 630 + return 1; 631 + } 632 + 633 + /* verify dfa xindexes are in range of transition tables */ 634 + static bool verify_dfa_xindex(struct aa_dfa *dfa, int table_size) 635 + { 636 + int i; 637 + for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) { 638 + if (!verify_xindex(dfa_user_xindex(dfa, i), table_size)) 639 + return 0; 640 + if (!verify_xindex(dfa_other_xindex(dfa, i), table_size)) 641 + return 0; 642 + } 643 + return 1; 644 + } 645 + 646 + /** 647 + * verify_profile - Do post unpack analysis to verify profile consistency 648 + * @profile: profile to verify (NOT NULL) 649 + * 650 + * Returns: 0 if passes verification else error 651 + */ 652 + static int verify_profile(struct aa_profile *profile) 653 + { 654 + if (aa_g_paranoid_load) { 655 + if (profile->file.dfa && 656 + !verify_dfa_xindex(profile->file.dfa, 657 + profile->file.trans.size)) { 658 + audit_iface(profile, NULL, "Invalid named transition", 659 + NULL, -EPROTO); 660 + return -EPROTO; 661 + } 662 + } 663 + 664 + return 0; 665 + } 666 + 667 + /** 668 + * aa_unpack - unpack packed binary profile data loaded from user space 669 + * @udata: user data copied to kmem (NOT NULL) 670 + * @size: the size of the user data 671 + * @ns: Returns namespace profile is in if specified else NULL (NOT NULL) 672 + * 673 + * Unpack user data and return refcounted allocated profile or ERR_PTR 674 + * 675 + * Returns: profile else error pointer if fails to unpack 676 + */ 677 + struct aa_profile *aa_unpack(void *udata, size_t size, const char **ns) 678 + { 679 + struct aa_profile *profile = NULL; 680 + int error; 681 + struct aa_ext e = { 682 + .start = udata, 683 + .end = udata + size, 684 + .pos = udata, 685 + }; 686 + 687 + error = verify_header(&e, ns); 688 + if (error) 689 + return ERR_PTR(error); 690 + 691 + profile = unpack_profile(&e); 692 + if (IS_ERR(profile)) 693 + return profile; 694 + 695 + error = verify_profile(profile); 696 + if (error) { 697 + aa_put_profile(profile); 698 + profile = ERR_PTR(error); 699 + } 700 + 701 + /* return refcount */ 702 + return profile; 703 + }
+170
security/apparmor/procattr.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor /proc/<pid>/attr/ interface functions 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #include "include/apparmor.h" 16 + #include "include/context.h" 17 + #include "include/policy.h" 18 + #include "include/domain.h" 19 + 20 + 21 + /** 22 + * aa_getprocattr - Return the profile information for @profile 23 + * @profile: the profile to print profile info about (NOT NULL) 24 + * @string: Returns - string containing the profile info (NOT NULL) 25 + * 26 + * Returns: length of @string on success else error on failure 27 + * 28 + * Requires: profile != NULL 29 + * 30 + * Creates a string containing the namespace_name://profile_name for 31 + * @profile. 32 + * 33 + * Returns: size of string placed in @string else error code on failure 34 + */ 35 + int aa_getprocattr(struct aa_profile *profile, char **string) 36 + { 37 + char *str; 38 + int len = 0, mode_len = 0, ns_len = 0, name_len; 39 + const char *mode_str = profile_mode_names[profile->mode]; 40 + const char *ns_name = NULL; 41 + struct aa_namespace *ns = profile->ns; 42 + struct aa_namespace *current_ns = __aa_current_profile()->ns; 43 + char *s; 44 + 45 + if (!aa_ns_visible(current_ns, ns)) 46 + return -EACCES; 47 + 48 + ns_name = aa_ns_name(current_ns, ns); 49 + ns_len = strlen(ns_name); 50 + 51 + /* if the visible ns_name is > 0 increase size for : :// seperator */ 52 + if (ns_len) 53 + ns_len += 4; 54 + 55 + /* unconfined profiles don't have a mode string appended */ 56 + if (!unconfined(profile)) 57 + mode_len = strlen(mode_str) + 3; /* + 3 for _() */ 58 + 59 + name_len = strlen(profile->base.hname); 60 + len = mode_len + ns_len + name_len + 1; /* + 1 for \n */ 61 + s = str = kmalloc(len + 1, GFP_KERNEL); /* + 1 \0 */ 62 + if (!str) 63 + return -ENOMEM; 64 + 65 + if (ns_len) { 66 + /* skip over prefix current_ns->base.hname and separating // */ 67 + sprintf(s, ":%s://", ns_name); 68 + s += ns_len; 69 + } 70 + if (unconfined(profile)) 71 + /* mode string not being appended */ 72 + sprintf(s, "%s\n", profile->base.hname); 73 + else 74 + sprintf(s, "%s (%s)\n", profile->base.hname, mode_str); 75 + *string = str; 76 + 77 + /* NOTE: len does not include \0 of string, not saved as part of file */ 78 + return len; 79 + } 80 + 81 + /** 82 + * split_token_from_name - separate a string of form <token>^<name> 83 + * @op: operation being checked 84 + * @args: string to parse (NOT NULL) 85 + * @token: stores returned parsed token value (NOT NULL) 86 + * 87 + * Returns: start position of name after token else NULL on failure 88 + */ 89 + static char *split_token_from_name(int op, char *args, u64 * token) 90 + { 91 + char *name; 92 + 93 + *token = simple_strtoull(args, &name, 16); 94 + if ((name == args) || *name != '^') { 95 + AA_ERROR("%s: Invalid input '%s'", op_table[op], args); 96 + return ERR_PTR(-EINVAL); 97 + } 98 + 99 + name++; /* skip ^ */ 100 + if (!*name) 101 + name = NULL; 102 + return name; 103 + } 104 + 105 + /** 106 + * aa_setprocattr_chagnehat - handle procattr interface to change_hat 107 + * @args: args received from writing to /proc/<pid>/attr/current (NOT NULL) 108 + * @size: size of the args 109 + * @test: true if this is a test of change_hat permissions 110 + * 111 + * Returns: %0 or error code if change_hat fails 112 + */ 113 + int aa_setprocattr_changehat(char *args, size_t size, int test) 114 + { 115 + char *hat; 116 + u64 token; 117 + const char *hats[16]; /* current hard limit on # of names */ 118 + int count = 0; 119 + 120 + hat = split_token_from_name(OP_CHANGE_HAT, args, &token); 121 + if (IS_ERR(hat)) 122 + return PTR_ERR(hat); 123 + 124 + if (!hat && !token) { 125 + AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic"); 126 + return -EINVAL; 127 + } 128 + 129 + if (hat) { 130 + /* set up hat name vector, args guaranteed null terminated 131 + * at args[size] by setprocattr. 132 + * 133 + * If there are multiple hat names in the buffer each is 134 + * separated by a \0. Ie. userspace writes them pre tokenized 135 + */ 136 + char *end = args + size; 137 + for (count = 0; (hat < end) && count < 16; ++count) { 138 + char *next = hat + strlen(hat) + 1; 139 + hats[count] = hat; 140 + hat = next; 141 + } 142 + } 143 + 144 + AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n", 145 + __func__, token, hat ? hat : NULL); 146 + 147 + return aa_change_hat(hats, count, token, test); 148 + } 149 + 150 + /** 151 + * aa_setprocattr_changeprofile - handle procattr interface to changeprofile 152 + * @fqname: args received from writting to /proc/<pid>/attr/current (NOT NULL) 153 + * @onexec: true if change_profile should be delayed until exec 154 + * @test: true if this is a test of change_profile permissions 155 + * 156 + * Returns: %0 or error code if change_profile fails 157 + */ 158 + int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test) 159 + { 160 + char *name, *ns_name; 161 + 162 + name = aa_split_fqname(fqname, &ns_name); 163 + return aa_change_profile(ns_name, name, onexec, test); 164 + } 165 + 166 + int aa_setprocattr_permipc(char *fqname) 167 + { 168 + /* TODO: add ipc permission querying */ 169 + return -ENOTSUPP; 170 + }
+134
security/apparmor/resource.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor resource mediation and attachment 5 + * 6 + * Copyright (C) 1998-2008 Novell/SUSE 7 + * Copyright 2009-2010 Canonical Ltd. 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License as 11 + * published by the Free Software Foundation, version 2 of the 12 + * License. 13 + */ 14 + 15 + #include <linux/audit.h> 16 + 17 + #include "include/audit.h" 18 + #include "include/resource.h" 19 + #include "include/policy.h" 20 + 21 + /* 22 + * Table of rlimit names: we generate it from resource.h. 23 + */ 24 + #include "rlim_names.h" 25 + 26 + /* audit callback for resource specific fields */ 27 + static void audit_cb(struct audit_buffer *ab, void *va) 28 + { 29 + struct common_audit_data *sa = va; 30 + 31 + audit_log_format(ab, " rlimit=%s value=%lu", 32 + rlim_names[sa->aad.rlim.rlim], sa->aad.rlim.max); 33 + } 34 + 35 + /** 36 + * audit_resource - audit setting resource limit 37 + * @profile: profile being enforced (NOT NULL) 38 + * @resoure: rlimit being auditing 39 + * @value: value being set 40 + * @error: error value 41 + * 42 + * Returns: 0 or sa->error else other error code on failure 43 + */ 44 + static int audit_resource(struct aa_profile *profile, unsigned int resource, 45 + unsigned long value, int error) 46 + { 47 + struct common_audit_data sa; 48 + 49 + COMMON_AUDIT_DATA_INIT(&sa, NONE); 50 + sa.aad.op = OP_SETRLIMIT, 51 + sa.aad.rlim.rlim = resource; 52 + sa.aad.rlim.max = value; 53 + sa.aad.error = error; 54 + return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_KERNEL, &sa, 55 + audit_cb); 56 + } 57 + 58 + /** 59 + * aa_map_resouce - map compiled policy resource to internal # 60 + * @resource: flattened policy resource number 61 + * 62 + * Returns: resource # for the current architecture. 63 + * 64 + * rlimit resource can vary based on architecture, map the compiled policy 65 + * resource # to the internal representation for the architecture. 66 + */ 67 + int aa_map_resource(int resource) 68 + { 69 + return rlim_map[resource]; 70 + } 71 + 72 + /** 73 + * aa_task_setrlimit - test permission to set an rlimit 74 + * @profile - profile confining the task (NOT NULL) 75 + * @resource - the resource being set 76 + * @new_rlim - the new resource limit (NOT NULL) 77 + * 78 + * Control raising the processes hard limit. 79 + * 80 + * Returns: 0 or error code if setting resource failed 81 + */ 82 + int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource, 83 + struct rlimit *new_rlim) 84 + { 85 + int error = 0; 86 + 87 + if (profile->rlimits.mask & (1 << resource) && 88 + new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max) 89 + 90 + error = audit_resource(profile, resource, new_rlim->rlim_max, 91 + -EACCES); 92 + 93 + return error; 94 + } 95 + 96 + /** 97 + * __aa_transition_rlimits - apply new profile rlimits 98 + * @old: old profile on task (NOT NULL) 99 + * @new: new profile with rlimits to apply (NOT NULL) 100 + */ 101 + void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new) 102 + { 103 + unsigned int mask = 0; 104 + struct rlimit *rlim, *initrlim; 105 + int i; 106 + 107 + /* for any rlimits the profile controlled reset the soft limit 108 + * to the less of the tasks hard limit and the init tasks soft limit 109 + */ 110 + if (old->rlimits.mask) { 111 + for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) { 112 + if (old->rlimits.mask & mask) { 113 + rlim = current->signal->rlim + i; 114 + initrlim = init_task.signal->rlim + i; 115 + rlim->rlim_cur = min(rlim->rlim_max, 116 + initrlim->rlim_cur); 117 + } 118 + } 119 + } 120 + 121 + /* set any new hard limits as dictated by the new profile */ 122 + if (!new->rlimits.mask) 123 + return; 124 + for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) { 125 + if (!(new->rlimits.mask & mask)) 126 + continue; 127 + 128 + rlim = current->signal->rlim + i; 129 + rlim->rlim_max = min(rlim->rlim_max, 130 + new->rlimits.limits[i].rlim_max); 131 + /* soft limit should not exceed hard limit */ 132 + rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max); 133 + } 134 + }
+55
security/apparmor/sid.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor security identifier (sid) manipulation fns 5 + * 6 + * Copyright 2009-2010 Canonical Ltd. 7 + * 8 + * This program is free software; you can redistribute it and/or 9 + * modify it under the terms of the GNU General Public License as 10 + * published by the Free Software Foundation, version 2 of the 11 + * License. 12 + * 13 + * 14 + * AppArmor allocates a unique sid for every profile loaded. If a profile 15 + * is replaced it receives the sid of the profile it is replacing. 16 + * 17 + * The sid value of 0 is invalid. 18 + */ 19 + 20 + #include <linux/spinlock.h> 21 + #include <linux/errno.h> 22 + #include <linux/err.h> 23 + 24 + #include "include/sid.h" 25 + 26 + /* global counter from which sids are allocated */ 27 + static u32 global_sid; 28 + static DEFINE_SPINLOCK(sid_lock); 29 + 30 + /* TODO FIXME: add sid to profile mapping, and sid recycling */ 31 + 32 + /** 33 + * aa_alloc_sid - allocate a new sid for a profile 34 + */ 35 + u32 aa_alloc_sid(void) 36 + { 37 + u32 sid; 38 + 39 + /* 40 + * TODO FIXME: sid recycling - part of profile mapping table 41 + */ 42 + spin_lock(&sid_lock); 43 + sid = (++global_sid); 44 + spin_unlock(&sid_lock); 45 + return sid; 46 + } 47 + 48 + /** 49 + * aa_free_sid - free a sid 50 + * @sid: sid to free 51 + */ 52 + void aa_free_sid(u32 sid) 53 + { 54 + ; /* NOP ATM */ 55 + }
+2 -3
security/capability.c
··· 27 27 return 0; 28 28 } 29 29 30 - static int cap_bprm_check_security (struct linux_binprm *bprm) 30 + static int cap_bprm_check_security(struct linux_binprm *bprm) 31 31 { 32 32 return 0; 33 33 } ··· 268 268 return 0; 269 269 } 270 270 271 - static int cap_path_truncate(struct path *path, loff_t length, 272 - unsigned int time_attrs) 271 + static int cap_path_truncate(struct path *path) 273 272 { 274 273 return 0; 275 274 }
+3 -1
security/inode.c
··· 86 86 int mode, dev_t dev) 87 87 { 88 88 struct inode *inode; 89 - int error = -EPERM; 89 + int error = -ENOMEM; 90 90 91 91 if (dentry->d_inode) 92 92 return -EEXIST; ··· 166 166 error = mkdir(parent->d_inode, *dentry, mode); 167 167 else 168 168 error = create(parent->d_inode, *dentry, mode); 169 + if (error) 170 + dput(*dentry); 169 171 } else 170 172 error = PTR_ERR(*dentry); 171 173 mutex_unlock(&parent->d_inode->i_mutex);
+6 -3
security/integrity/ima/ima_fs.c
··· 45 45 } 46 46 47 47 static const struct file_operations ima_htable_violations_ops = { 48 - .read = ima_show_htable_violations 48 + .read = ima_show_htable_violations, 49 + .llseek = generic_file_llseek, 49 50 }; 50 51 51 52 static ssize_t ima_show_measurements_count(struct file *filp, ··· 58 57 } 59 58 60 59 static const struct file_operations ima_measurements_count_ops = { 61 - .read = ima_show_measurements_count 60 + .read = ima_show_measurements_count, 61 + .llseek = generic_file_llseek, 62 62 }; 63 63 64 64 /* returns pointer to hlist_node */ ··· 321 319 static const struct file_operations ima_measure_policy_ops = { 322 320 .open = ima_open_policy, 323 321 .write = ima_write_policy, 324 - .release = ima_release_policy 322 + .release = ima_release_policy, 323 + .llseek = generic_file_llseek, 325 324 }; 326 325 327 326 int __init ima_fs_init(void)
+5
security/keys/internal.h
··· 114 114 const void *description, 115 115 key_match_func_t match); 116 116 117 + extern key_ref_t search_my_process_keyrings(struct key_type *type, 118 + const void *description, 119 + key_match_func_t match, 120 + const struct cred *cred); 117 121 extern key_ref_t search_process_keyrings(struct key_type *type, 118 122 const void *description, 119 123 key_match_func_t match, ··· 138 134 struct key *dest_keyring, 139 135 unsigned long flags); 140 136 137 + extern int lookup_user_key_possessed(const struct key *key, const void *target); 141 138 extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, 142 139 key_perm_t perm); 143 140 #define KEY_LOOKUP_CREATE 0x01
+21 -8
security/keys/keyctl.c
··· 505 505 506 506 ret = snprintf(tmpbuf, PAGE_SIZE - 1, 507 507 "%s;%d;%d;%08x;%s", 508 - key_ref_to_ptr(key_ref)->type->name, 509 - key_ref_to_ptr(key_ref)->uid, 510 - key_ref_to_ptr(key_ref)->gid, 511 - key_ref_to_ptr(key_ref)->perm, 512 - key_ref_to_ptr(key_ref)->description ? 513 - key_ref_to_ptr(key_ref)->description : "" 514 - ); 508 + key->type->name, 509 + key->uid, 510 + key->gid, 511 + key->perm, 512 + key->description ?: ""); 515 513 516 514 /* include a NUL char at the end of the data */ 517 515 if (ret > PAGE_SIZE - 1) ··· 1089 1091 long keyctl_set_timeout(key_serial_t id, unsigned timeout) 1090 1092 { 1091 1093 struct timespec now; 1092 - struct key *key; 1094 + struct key *key, *instkey; 1093 1095 key_ref_t key_ref; 1094 1096 time_t expiry; 1095 1097 long ret; ··· 1097 1099 key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL, 1098 1100 KEY_SETATTR); 1099 1101 if (IS_ERR(key_ref)) { 1102 + /* setting the timeout on a key under construction is permitted 1103 + * if we have the authorisation token handy */ 1104 + if (PTR_ERR(key_ref) == -EACCES) { 1105 + instkey = key_get_instantiation_authkey(id); 1106 + if (!IS_ERR(instkey)) { 1107 + key_put(instkey); 1108 + key_ref = lookup_user_key(id, 1109 + KEY_LOOKUP_PARTIAL, 1110 + 0); 1111 + if (!IS_ERR(key_ref)) 1112 + goto okay; 1113 + } 1114 + } 1115 + 1100 1116 ret = PTR_ERR(key_ref); 1101 1117 goto error; 1102 1118 } 1103 1119 1120 + okay: 1104 1121 key = key_ref_to_ptr(key_ref); 1105 1122 1106 1123 /* make the changes with the locks held to prevent races */
+18 -2
security/keys/proc.c
··· 184 184 185 185 static int proc_keys_show(struct seq_file *m, void *v) 186 186 { 187 + const struct cred *cred = current_cred(); 187 188 struct rb_node *_p = v; 188 189 struct key *key = rb_entry(_p, struct key, serial_node); 189 190 struct timespec now; 190 191 unsigned long timo; 192 + key_ref_t key_ref, skey_ref; 191 193 char xbuf[12]; 192 194 int rc; 195 + 196 + key_ref = make_key_ref(key, 0); 197 + 198 + /* determine if the key is possessed by this process (a test we can 199 + * skip if the key does not indicate the possessor can view it 200 + */ 201 + if (key->perm & KEY_POS_VIEW) { 202 + skey_ref = search_my_process_keyrings(key->type, key, 203 + lookup_user_key_possessed, 204 + cred); 205 + if (!IS_ERR(skey_ref)) { 206 + key_ref_put(skey_ref); 207 + key_ref = make_key_ref(key, 1); 208 + } 209 + } 193 210 194 211 /* check whether the current task is allowed to view the key (assuming 195 212 * non-possession) 196 213 * - the caller holds a spinlock, and thus the RCU read lock, making our 197 214 * access to __current_cred() safe 198 215 */ 199 - rc = key_task_permission(make_key_ref(key, 0), current_cred(), 200 - KEY_VIEW); 216 + rc = key_task_permission(key_ref, cred, KEY_VIEW); 201 217 if (rc < 0) 202 218 return 0; 203 219
+43 -21
security/keys/process_keys.c
··· 309 309 310 310 /*****************************************************************************/ 311 311 /* 312 - * search the process keyrings for the first matching key 312 + * search only my process keyrings for the first matching key 313 313 * - we use the supplied match function to see if the description (or other 314 314 * feature of interest) matches 315 315 * - we return -EAGAIN if we didn't find any matching key 316 316 * - we return -ENOKEY if we found only negative matching keys 317 317 */ 318 - key_ref_t search_process_keyrings(struct key_type *type, 319 - const void *description, 320 - key_match_func_t match, 321 - const struct cred *cred) 318 + key_ref_t search_my_process_keyrings(struct key_type *type, 319 + const void *description, 320 + key_match_func_t match, 321 + const struct cred *cred) 322 322 { 323 - struct request_key_auth *rka; 324 323 key_ref_t key_ref, ret, err; 325 - 326 - might_sleep(); 327 324 328 325 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were 329 326 * searchable, but we failed to find a key or we found a negative key; ··· 421 424 } 422 425 } 423 426 427 + /* no key - decide on the error we're going to go for */ 428 + key_ref = ret ? ret : err; 429 + 430 + found: 431 + return key_ref; 432 + } 433 + 434 + /*****************************************************************************/ 435 + /* 436 + * search the process keyrings for the first matching key 437 + * - we use the supplied match function to see if the description (or other 438 + * feature of interest) matches 439 + * - we return -EAGAIN if we didn't find any matching key 440 + * - we return -ENOKEY if we found only negative matching keys 441 + */ 442 + key_ref_t search_process_keyrings(struct key_type *type, 443 + const void *description, 444 + key_match_func_t match, 445 + const struct cred *cred) 446 + { 447 + struct request_key_auth *rka; 448 + key_ref_t key_ref, ret = ERR_PTR(-EACCES), err; 449 + 450 + might_sleep(); 451 + 452 + key_ref = search_my_process_keyrings(type, description, match, cred); 453 + if (!IS_ERR(key_ref)) 454 + goto found; 455 + err = key_ref; 456 + 424 457 /* if this process has an instantiation authorisation key, then we also 425 458 * search the keyrings of the process mentioned there 426 459 * - we don't permit access to request_key auth keys via this method ··· 473 446 if (!IS_ERR(key_ref)) 474 447 goto found; 475 448 476 - switch (PTR_ERR(key_ref)) { 477 - case -EAGAIN: /* no key */ 478 - if (ret) 479 - break; 480 - case -ENOKEY: /* negative key */ 481 - ret = key_ref; 482 - break; 483 - default: 484 - err = key_ref; 485 - break; 486 - } 449 + ret = key_ref; 487 450 } else { 488 451 up_read(&cred->request_key_auth->sem); 489 452 } 490 453 } 491 454 492 455 /* no key - decide on the error we're going to go for */ 493 - key_ref = ret ? ret : err; 456 + if (err == ERR_PTR(-ENOKEY) || ret == ERR_PTR(-ENOKEY)) 457 + key_ref = ERR_PTR(-ENOKEY); 458 + else if (err == ERR_PTR(-EACCES)) 459 + key_ref = ret; 460 + else 461 + key_ref = err; 494 462 495 463 found: 496 464 return key_ref; ··· 496 474 /* 497 475 * see if the key we're looking at is the target key 498 476 */ 499 - static int lookup_user_key_possessed(const struct key *key, const void *target) 477 + int lookup_user_key_possessed(const struct key *key, const void *target) 500 478 { 501 479 return key == target; 502 480
+1
security/keys/request_key.c
··· 144 144 prkey = 0; 145 145 if (cred->tgcred->process_keyring) 146 146 prkey = cred->tgcred->process_keyring->serial; 147 + sprintf(keyring_str[1], "%d", prkey); 147 148 148 149 rcu_read_lock(); 149 150 session = rcu_dereference(cred->tgcred->session_keyring);
+2 -3
security/security.c
··· 417 417 new_dentry); 418 418 } 419 419 420 - int security_path_truncate(struct path *path, loff_t length, 421 - unsigned int time_attrs) 420 + int security_path_truncate(struct path *path) 422 421 { 423 422 if (unlikely(IS_PRIVATE(path->dentry->d_inode))) 424 423 return 0; 425 - return security_ops->path_truncate(path, length, time_attrs); 424 + return security_ops->path_truncate(path); 426 425 } 427 426 428 427 int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
+22 -3
security/selinux/avc.c
··· 288 288 if (!node) 289 289 goto out; 290 290 291 - INIT_RCU_HEAD(&node->rhead); 292 291 INIT_HLIST_NODE(&node->list); 293 292 avc_cache_stats_incr(allocations); 294 293 ··· 488 489 struct common_audit_data stack_data; 489 490 u32 denied, audited; 490 491 denied = requested & ~avd->allowed; 491 - if (denied) 492 + if (denied) { 492 493 audited = denied & avd->auditdeny; 493 - else if (result) 494 + /* 495 + * a->selinux_audit_data.auditdeny is TRICKY! Setting a bit in 496 + * this field means that ANY denials should NOT be audited if 497 + * the policy contains an explicit dontaudit rule for that 498 + * permission. Take notice that this is unrelated to the 499 + * actual permissions that were denied. As an example lets 500 + * assume: 501 + * 502 + * denied == READ 503 + * avd.auditdeny & ACCESS == 0 (not set means explicit rule) 504 + * selinux_audit_data.auditdeny & ACCESS == 1 505 + * 506 + * We will NOT audit the denial even though the denied 507 + * permission was READ and the auditdeny checks were for 508 + * ACCESS 509 + */ 510 + if (a && 511 + a->selinux_audit_data.auditdeny && 512 + !(a->selinux_audit_data.auditdeny & avd->auditdeny)) 513 + audited = 0; 514 + } else if (result) 494 515 audited = denied = requested; 495 516 else 496 517 audited = requested & avd->auditallow;
+114 -178
security/selinux/hooks.c
··· 87 87 #include "netlabel.h" 88 88 #include "audit.h" 89 89 90 - #define XATTR_SELINUX_SUFFIX "selinux" 91 - #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX 92 - 93 90 #define NUM_SEL_MNT_OPTS 5 94 91 95 92 extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); ··· 185 188 */ 186 189 static inline u32 current_sid(void) 187 190 { 188 - const struct task_security_struct *tsec = current_cred()->security; 191 + const struct task_security_struct *tsec = current_security(); 189 192 190 193 return tsec->sid; 191 194 } ··· 274 277 struct superblock_security_struct *sbsec = sb->s_security; 275 278 sb->s_security = NULL; 276 279 kfree(sbsec); 277 - } 278 - 279 - static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) 280 - { 281 - struct sk_security_struct *sksec; 282 - 283 - sksec = kzalloc(sizeof(*sksec), priority); 284 - if (!sksec) 285 - return -ENOMEM; 286 - 287 - sksec->peer_sid = SECINITSID_UNLABELED; 288 - sksec->sid = SECINITSID_UNLABELED; 289 - sk->sk_security = sksec; 290 - 291 - selinux_netlbl_sk_security_reset(sksec); 292 - 293 - return 0; 294 - } 295 - 296 - static void sk_free_security(struct sock *sk) 297 - { 298 - struct sk_security_struct *sksec = sk->sk_security; 299 - 300 - sk->sk_security = NULL; 301 - selinux_netlbl_sk_security_free(sksec); 302 - kfree(sksec); 303 280 } 304 281 305 282 /* The security server must be initialized before ··· 1555 1584 struct dentry *dentry, 1556 1585 u16 tclass) 1557 1586 { 1558 - const struct cred *cred = current_cred(); 1559 - const struct task_security_struct *tsec = cred->security; 1587 + const struct task_security_struct *tsec = current_security(); 1560 1588 struct inode_security_struct *dsec; 1561 1589 struct superblock_security_struct *sbsec; 1562 1590 u32 sid, newsid; ··· 1776 1806 { 1777 1807 u32 av = file_to_av(file); 1778 1808 1779 - if (selinux_policycap_openperm) { 1780 - mode_t mode = file->f_path.dentry->d_inode->i_mode; 1781 - /* 1782 - * lnk files and socks do not really have an 'open' 1783 - */ 1784 - if (S_ISREG(mode)) 1785 - av |= FILE__OPEN; 1786 - else if (S_ISCHR(mode)) 1787 - av |= CHR_FILE__OPEN; 1788 - else if (S_ISBLK(mode)) 1789 - av |= BLK_FILE__OPEN; 1790 - else if (S_ISFIFO(mode)) 1791 - av |= FIFO_FILE__OPEN; 1792 - else if (S_ISDIR(mode)) 1793 - av |= DIR__OPEN; 1794 - else if (S_ISSOCK(mode)) 1795 - av |= SOCK_FILE__OPEN; 1796 - else 1797 - printk(KERN_ERR "SELinux: WARNING: inside %s with " 1798 - "unknown mode:%o\n", __func__, mode); 1799 - } 1809 + if (selinux_policycap_openperm) 1810 + av |= FILE__OPEN; 1811 + 1800 1812 return av; 1801 1813 } 1802 1814 ··· 2135 2183 2136 2184 static int selinux_bprm_secureexec(struct linux_binprm *bprm) 2137 2185 { 2138 - const struct cred *cred = current_cred(); 2139 - const struct task_security_struct *tsec = cred->security; 2186 + const struct task_security_struct *tsec = current_security(); 2140 2187 u32 sid, osid; 2141 2188 int atsecure = 0; 2142 2189 ··· 2510 2559 char **name, void **value, 2511 2560 size_t *len) 2512 2561 { 2513 - const struct cred *cred = current_cred(); 2514 - const struct task_security_struct *tsec = cred->security; 2562 + const struct task_security_struct *tsec = current_security(); 2515 2563 struct inode_security_struct *dsec; 2516 2564 struct superblock_security_struct *sbsec; 2517 2565 u32 sid, newsid, clen; ··· 2626 2676 static int selinux_inode_permission(struct inode *inode, int mask) 2627 2677 { 2628 2678 const struct cred *cred = current_cred(); 2679 + struct common_audit_data ad; 2680 + u32 perms; 2681 + bool from_access; 2629 2682 2630 - if (!mask) { 2631 - /* No permission to check. Existence test. */ 2683 + from_access = mask & MAY_ACCESS; 2684 + mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); 2685 + 2686 + /* No permission to check. Existence test. */ 2687 + if (!mask) 2632 2688 return 0; 2633 - } 2634 2689 2635 - return inode_has_perm(cred, inode, 2636 - file_mask_to_av(inode->i_mode, mask), NULL); 2690 + COMMON_AUDIT_DATA_INIT(&ad, FS); 2691 + ad.u.fs.inode = inode; 2692 + 2693 + if (from_access) 2694 + ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS; 2695 + 2696 + perms = file_mask_to_av(inode->i_mode, mask); 2697 + 2698 + return inode_has_perm(cred, inode, perms, &ad); 2637 2699 } 2638 2700 2639 2701 static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) ··· 3633 3671 } 3634 3672 3635 3673 /* socket security operations */ 3636 - static int socket_has_perm(struct task_struct *task, struct socket *sock, 3637 - u32 perms) 3674 + 3675 + static u32 socket_sockcreate_sid(const struct task_security_struct *tsec) 3638 3676 { 3639 - struct inode_security_struct *isec; 3677 + return tsec->sockcreate_sid ? : tsec->sid; 3678 + } 3679 + 3680 + static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) 3681 + { 3682 + struct sk_security_struct *sksec = sk->sk_security; 3640 3683 struct common_audit_data ad; 3641 - u32 sid; 3642 - int err = 0; 3684 + u32 tsid = task_sid(task); 3643 3685 3644 - isec = SOCK_INODE(sock)->i_security; 3645 - 3646 - if (isec->sid == SECINITSID_KERNEL) 3647 - goto out; 3648 - sid = task_sid(task); 3686 + if (sksec->sid == SECINITSID_KERNEL) 3687 + return 0; 3649 3688 3650 3689 COMMON_AUDIT_DATA_INIT(&ad, NET); 3651 - ad.u.net.sk = sock->sk; 3652 - err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); 3690 + ad.u.net.sk = sk; 3653 3691 3654 - out: 3655 - return err; 3692 + return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad); 3656 3693 } 3657 3694 3658 3695 static int selinux_socket_create(int family, int type, 3659 3696 int protocol, int kern) 3660 3697 { 3661 - const struct cred *cred = current_cred(); 3662 - const struct task_security_struct *tsec = cred->security; 3663 - u32 sid, newsid; 3698 + const struct task_security_struct *tsec = current_security(); 3699 + u32 newsid; 3664 3700 u16 secclass; 3665 - int err = 0; 3666 3701 3667 3702 if (kern) 3668 - goto out; 3703 + return 0; 3669 3704 3670 - sid = tsec->sid; 3671 - newsid = tsec->sockcreate_sid ?: sid; 3672 - 3705 + newsid = socket_sockcreate_sid(tsec); 3673 3706 secclass = socket_type_to_security_class(family, type, protocol); 3674 - err = avc_has_perm(sid, newsid, secclass, SOCKET__CREATE, NULL); 3675 - 3676 - out: 3677 - return err; 3707 + return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); 3678 3708 } 3679 3709 3680 3710 static int selinux_socket_post_create(struct socket *sock, int family, 3681 3711 int type, int protocol, int kern) 3682 3712 { 3683 - const struct cred *cred = current_cred(); 3684 - const struct task_security_struct *tsec = cred->security; 3685 - struct inode_security_struct *isec; 3713 + const struct task_security_struct *tsec = current_security(); 3714 + struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; 3686 3715 struct sk_security_struct *sksec; 3687 - u32 sid, newsid; 3688 3716 int err = 0; 3689 - 3690 - sid = tsec->sid; 3691 - newsid = tsec->sockcreate_sid; 3692 - 3693 - isec = SOCK_INODE(sock)->i_security; 3694 3717 3695 3718 if (kern) 3696 3719 isec->sid = SECINITSID_KERNEL; 3697 - else if (newsid) 3698 - isec->sid = newsid; 3699 3720 else 3700 - isec->sid = sid; 3721 + isec->sid = socket_sockcreate_sid(tsec); 3701 3722 3702 3723 isec->sclass = socket_type_to_security_class(family, type, protocol); 3703 3724 isec->initialized = 1; ··· 3701 3756 3702 3757 static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) 3703 3758 { 3759 + struct sock *sk = sock->sk; 3704 3760 u16 family; 3705 3761 int err; 3706 3762 3707 - err = socket_has_perm(current, sock, SOCKET__BIND); 3763 + err = sock_has_perm(current, sk, SOCKET__BIND); 3708 3764 if (err) 3709 3765 goto out; 3710 3766 ··· 3714 3768 * Multiple address binding for SCTP is not supported yet: we just 3715 3769 * check the first address now. 3716 3770 */ 3717 - family = sock->sk->sk_family; 3771 + family = sk->sk_family; 3718 3772 if (family == PF_INET || family == PF_INET6) { 3719 3773 char *addrp; 3720 - struct inode_security_struct *isec; 3774 + struct sk_security_struct *sksec = sk->sk_security; 3721 3775 struct common_audit_data ad; 3722 3776 struct sockaddr_in *addr4 = NULL; 3723 3777 struct sockaddr_in6 *addr6 = NULL; 3724 3778 unsigned short snum; 3725 - struct sock *sk = sock->sk; 3726 3779 u32 sid, node_perm; 3727 - 3728 - isec = SOCK_INODE(sock)->i_security; 3729 3780 3730 3781 if (family == PF_INET) { 3731 3782 addr4 = (struct sockaddr_in *)address; ··· 3747 3804 COMMON_AUDIT_DATA_INIT(&ad, NET); 3748 3805 ad.u.net.sport = htons(snum); 3749 3806 ad.u.net.family = family; 3750 - err = avc_has_perm(isec->sid, sid, 3751 - isec->sclass, 3807 + err = avc_has_perm(sksec->sid, sid, 3808 + sksec->sclass, 3752 3809 SOCKET__NAME_BIND, &ad); 3753 3810 if (err) 3754 3811 goto out; 3755 3812 } 3756 3813 } 3757 3814 3758 - switch (isec->sclass) { 3815 + switch (sksec->sclass) { 3759 3816 case SECCLASS_TCP_SOCKET: 3760 3817 node_perm = TCP_SOCKET__NODE_BIND; 3761 3818 break; ··· 3786 3843 else 3787 3844 ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); 3788 3845 3789 - err = avc_has_perm(isec->sid, sid, 3790 - isec->sclass, node_perm, &ad); 3846 + err = avc_has_perm(sksec->sid, sid, 3847 + sksec->sclass, node_perm, &ad); 3791 3848 if (err) 3792 3849 goto out; 3793 3850 } ··· 3798 3855 static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) 3799 3856 { 3800 3857 struct sock *sk = sock->sk; 3801 - struct inode_security_struct *isec; 3858 + struct sk_security_struct *sksec = sk->sk_security; 3802 3859 int err; 3803 3860 3804 - err = socket_has_perm(current, sock, SOCKET__CONNECT); 3861 + err = sock_has_perm(current, sk, SOCKET__CONNECT); 3805 3862 if (err) 3806 3863 return err; 3807 3864 3808 3865 /* 3809 3866 * If a TCP or DCCP socket, check name_connect permission for the port. 3810 3867 */ 3811 - isec = SOCK_INODE(sock)->i_security; 3812 - if (isec->sclass == SECCLASS_TCP_SOCKET || 3813 - isec->sclass == SECCLASS_DCCP_SOCKET) { 3868 + if (sksec->sclass == SECCLASS_TCP_SOCKET || 3869 + sksec->sclass == SECCLASS_DCCP_SOCKET) { 3814 3870 struct common_audit_data ad; 3815 3871 struct sockaddr_in *addr4 = NULL; 3816 3872 struct sockaddr_in6 *addr6 = NULL; ··· 3832 3890 if (err) 3833 3891 goto out; 3834 3892 3835 - perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? 3893 + perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? 3836 3894 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; 3837 3895 3838 3896 COMMON_AUDIT_DATA_INIT(&ad, NET); 3839 3897 ad.u.net.dport = htons(snum); 3840 3898 ad.u.net.family = sk->sk_family; 3841 - err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); 3899 + err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); 3842 3900 if (err) 3843 3901 goto out; 3844 3902 } ··· 3851 3909 3852 3910 static int selinux_socket_listen(struct socket *sock, int backlog) 3853 3911 { 3854 - return socket_has_perm(current, sock, SOCKET__LISTEN); 3912 + return sock_has_perm(current, sock->sk, SOCKET__LISTEN); 3855 3913 } 3856 3914 3857 3915 static int selinux_socket_accept(struct socket *sock, struct socket *newsock) ··· 3860 3918 struct inode_security_struct *isec; 3861 3919 struct inode_security_struct *newisec; 3862 3920 3863 - err = socket_has_perm(current, sock, SOCKET__ACCEPT); 3921 + err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT); 3864 3922 if (err) 3865 3923 return err; 3866 3924 ··· 3877 3935 static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, 3878 3936 int size) 3879 3937 { 3880 - return socket_has_perm(current, sock, SOCKET__WRITE); 3938 + return sock_has_perm(current, sock->sk, SOCKET__WRITE); 3881 3939 } 3882 3940 3883 3941 static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, 3884 3942 int size, int flags) 3885 3943 { 3886 - return socket_has_perm(current, sock, SOCKET__READ); 3944 + return sock_has_perm(current, sock->sk, SOCKET__READ); 3887 3945 } 3888 3946 3889 3947 static int selinux_socket_getsockname(struct socket *sock) 3890 3948 { 3891 - return socket_has_perm(current, sock, SOCKET__GETATTR); 3949 + return sock_has_perm(current, sock->sk, SOCKET__GETATTR); 3892 3950 } 3893 3951 3894 3952 static int selinux_socket_getpeername(struct socket *sock) 3895 3953 { 3896 - return socket_has_perm(current, sock, SOCKET__GETATTR); 3954 + return sock_has_perm(current, sock->sk, SOCKET__GETATTR); 3897 3955 } 3898 3956 3899 3957 static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) 3900 3958 { 3901 3959 int err; 3902 3960 3903 - err = socket_has_perm(current, sock, SOCKET__SETOPT); 3961 + err = sock_has_perm(current, sock->sk, SOCKET__SETOPT); 3904 3962 if (err) 3905 3963 return err; 3906 3964 ··· 3910 3968 static int selinux_socket_getsockopt(struct socket *sock, int level, 3911 3969 int optname) 3912 3970 { 3913 - return socket_has_perm(current, sock, SOCKET__GETOPT); 3971 + return sock_has_perm(current, sock->sk, SOCKET__GETOPT); 3914 3972 } 3915 3973 3916 3974 static int selinux_socket_shutdown(struct socket *sock, int how) 3917 3975 { 3918 - return socket_has_perm(current, sock, SOCKET__SHUTDOWN); 3976 + return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN); 3919 3977 } 3920 3978 3921 3979 static int selinux_socket_unix_stream_connect(struct socket *sock, 3922 3980 struct socket *other, 3923 3981 struct sock *newsk) 3924 3982 { 3925 - struct sk_security_struct *sksec; 3926 - struct inode_security_struct *isec; 3927 - struct inode_security_struct *other_isec; 3983 + struct sk_security_struct *sksec_sock = sock->sk->sk_security; 3984 + struct sk_security_struct *sksec_other = other->sk->sk_security; 3985 + struct sk_security_struct *sksec_new = newsk->sk_security; 3928 3986 struct common_audit_data ad; 3929 3987 int err; 3930 - 3931 - isec = SOCK_INODE(sock)->i_security; 3932 - other_isec = SOCK_INODE(other)->i_security; 3933 3988 3934 3989 COMMON_AUDIT_DATA_INIT(&ad, NET); 3935 3990 ad.u.net.sk = other->sk; 3936 3991 3937 - err = avc_has_perm(isec->sid, other_isec->sid, 3938 - isec->sclass, 3992 + err = avc_has_perm(sksec_sock->sid, sksec_other->sid, 3993 + sksec_other->sclass, 3939 3994 UNIX_STREAM_SOCKET__CONNECTTO, &ad); 3940 3995 if (err) 3941 3996 return err; 3942 3997 3943 - /* connecting socket */ 3944 - sksec = sock->sk->sk_security; 3945 - sksec->peer_sid = other_isec->sid; 3946 - 3947 3998 /* server child socket */ 3948 - sksec = newsk->sk_security; 3949 - sksec->peer_sid = isec->sid; 3950 - err = security_sid_mls_copy(other_isec->sid, sksec->peer_sid, &sksec->sid); 3999 + sksec_new->peer_sid = sksec_sock->sid; 4000 + err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid, 4001 + &sksec_new->sid); 4002 + if (err) 4003 + return err; 3951 4004 3952 - return err; 4005 + /* connecting socket */ 4006 + sksec_sock->peer_sid = sksec_new->sid; 4007 + 4008 + return 0; 3953 4009 } 3954 4010 3955 4011 static int selinux_socket_unix_may_send(struct socket *sock, 3956 4012 struct socket *other) 3957 4013 { 3958 - struct inode_security_struct *isec; 3959 - struct inode_security_struct *other_isec; 4014 + struct sk_security_struct *ssec = sock->sk->sk_security; 4015 + struct sk_security_struct *osec = other->sk->sk_security; 3960 4016 struct common_audit_data ad; 3961 - int err; 3962 - 3963 - isec = SOCK_INODE(sock)->i_security; 3964 - other_isec = SOCK_INODE(other)->i_security; 3965 4017 3966 4018 COMMON_AUDIT_DATA_INIT(&ad, NET); 3967 4019 ad.u.net.sk = other->sk; 3968 4020 3969 - err = avc_has_perm(isec->sid, other_isec->sid, 3970 - isec->sclass, SOCKET__SENDTO, &ad); 3971 - if (err) 3972 - return err; 3973 - 3974 - return 0; 4021 + return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, 4022 + &ad); 3975 4023 } 3976 4024 3977 4025 static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, ··· 4100 4168 int err = 0; 4101 4169 char *scontext; 4102 4170 u32 scontext_len; 4103 - struct sk_security_struct *sksec; 4104 - struct inode_security_struct *isec; 4171 + struct sk_security_struct *sksec = sock->sk->sk_security; 4105 4172 u32 peer_sid = SECSID_NULL; 4106 4173 4107 - isec = SOCK_INODE(sock)->i_security; 4108 - 4109 - if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET || 4110 - isec->sclass == SECCLASS_TCP_SOCKET) { 4111 - sksec = sock->sk->sk_security; 4174 + if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET || 4175 + sksec->sclass == SECCLASS_TCP_SOCKET) 4112 4176 peer_sid = sksec->peer_sid; 4113 - } 4114 - if (peer_sid == SECSID_NULL) { 4115 - err = -ENOPROTOOPT; 4116 - goto out; 4117 - } 4177 + if (peer_sid == SECSID_NULL) 4178 + return -ENOPROTOOPT; 4118 4179 4119 4180 err = security_sid_to_context(peer_sid, &scontext, &scontext_len); 4120 - 4121 4181 if (err) 4122 - goto out; 4182 + return err; 4123 4183 4124 4184 if (scontext_len > len) { 4125 4185 err = -ERANGE; ··· 4124 4200 out_len: 4125 4201 if (put_user(scontext_len, optlen)) 4126 4202 err = -EFAULT; 4127 - 4128 4203 kfree(scontext); 4129 - out: 4130 4204 return err; 4131 4205 } 4132 4206 ··· 4156 4234 4157 4235 static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) 4158 4236 { 4159 - return sk_alloc_security(sk, family, priority); 4237 + struct sk_security_struct *sksec; 4238 + 4239 + sksec = kzalloc(sizeof(*sksec), priority); 4240 + if (!sksec) 4241 + return -ENOMEM; 4242 + 4243 + sksec->peer_sid = SECINITSID_UNLABELED; 4244 + sksec->sid = SECINITSID_UNLABELED; 4245 + selinux_netlbl_sk_security_reset(sksec); 4246 + sk->sk_security = sksec; 4247 + 4248 + return 0; 4160 4249 } 4161 4250 4162 4251 static void selinux_sk_free_security(struct sock *sk) 4163 4252 { 4164 - sk_free_security(sk); 4253 + struct sk_security_struct *sksec = sk->sk_security; 4254 + 4255 + sk->sk_security = NULL; 4256 + selinux_netlbl_sk_security_free(sksec); 4257 + kfree(sksec); 4165 4258 } 4166 4259 4167 4260 static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) ··· 4336 4399 int err = 0; 4337 4400 u32 perm; 4338 4401 struct nlmsghdr *nlh; 4339 - struct socket *sock = sk->sk_socket; 4340 - struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; 4402 + struct sk_security_struct *sksec = sk->sk_security; 4341 4403 4342 4404 if (skb->len < NLMSG_SPACE(0)) { 4343 4405 err = -EINVAL; ··· 4344 4408 } 4345 4409 nlh = nlmsg_hdr(skb); 4346 4410 4347 - err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm); 4411 + err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm); 4348 4412 if (err) { 4349 4413 if (err == -EINVAL) { 4350 4414 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, 4351 4415 "SELinux: unrecognized netlink message" 4352 4416 " type=%hu for sclass=%hu\n", 4353 - nlh->nlmsg_type, isec->sclass); 4417 + nlh->nlmsg_type, sksec->sclass); 4354 4418 if (!selinux_enforcing || security_get_allow_unknown()) 4355 4419 err = 0; 4356 4420 } ··· 4361 4425 goto out; 4362 4426 } 4363 4427 4364 - err = socket_has_perm(current, sock, perm); 4428 + err = sock_has_perm(current, sk, perm); 4365 4429 out: 4366 4430 return err; 4367 4431 }
+8 -8
security/selinux/include/classmap.h
··· 2 2 "getattr", "setattr", "lock", "relabelfrom", "relabelto", "append" 3 3 4 4 #define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \ 5 - "rename", "execute", "swapon", "quotaon", "mounton" 5 + "rename", "execute", "swapon", "quotaon", "mounton", "audit_access", \ 6 + "open", "execmod" 6 7 7 8 #define COMMON_SOCK_PERMS COMMON_FILE_SOCK_PERMS, "bind", "connect", \ 8 9 "listen", "accept", "getopt", "setopt", "shutdown", "recvfrom", \ ··· 44 43 "quotaget", NULL } }, 45 44 { "file", 46 45 { COMMON_FILE_PERMS, 47 - "execute_no_trans", "entrypoint", "execmod", "open", NULL } }, 46 + "execute_no_trans", "entrypoint", NULL } }, 48 47 { "dir", 49 48 { COMMON_FILE_PERMS, "add_name", "remove_name", 50 - "reparent", "search", "rmdir", "open", NULL } }, 49 + "reparent", "search", "rmdir", NULL } }, 51 50 { "fd", { "use", NULL } }, 52 51 { "lnk_file", 53 52 { COMMON_FILE_PERMS, NULL } }, 54 53 { "chr_file", 55 - { COMMON_FILE_PERMS, 56 - "execute_no_trans", "entrypoint", "execmod", "open", NULL } }, 54 + { COMMON_FILE_PERMS, NULL } }, 57 55 { "blk_file", 58 - { COMMON_FILE_PERMS, "open", NULL } }, 56 + { COMMON_FILE_PERMS, NULL } }, 59 57 { "sock_file", 60 - { COMMON_FILE_PERMS, "open", NULL } }, 58 + { COMMON_FILE_PERMS, NULL } }, 61 59 { "fifo_file", 62 - { COMMON_FILE_PERMS, "open", NULL } }, 60 + { COMMON_FILE_PERMS, NULL } }, 63 61 { "socket", 64 62 { COMMON_SOCK_PERMS, NULL } }, 65 63 { "tcp_socket",
-2
security/selinux/netnode.c
··· 183 183 BUG(); 184 184 } 185 185 186 - INIT_RCU_HEAD(&node->rcu); 187 - 188 186 /* we need to impose a limit on the growth of the hash table so check 189 187 * this bucket to make sure it is within the specified bounds */ 190 188 list_add_rcu(&node->list, &sel_netnode_hash[idx].list);
+16
security/selinux/selinuxfs.c
··· 184 184 static const struct file_operations sel_enforce_ops = { 185 185 .read = sel_read_enforce, 186 186 .write = sel_write_enforce, 187 + .llseek = generic_file_llseek, 187 188 }; 188 189 189 190 static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf, ··· 202 201 203 202 static const struct file_operations sel_handle_unknown_ops = { 204 203 .read = sel_read_handle_unknown, 204 + .llseek = generic_file_llseek, 205 205 }; 206 206 207 207 #ifdef CONFIG_SECURITY_SELINUX_DISABLE ··· 253 251 254 252 static const struct file_operations sel_disable_ops = { 255 253 .write = sel_write_disable, 254 + .llseek = generic_file_llseek, 256 255 }; 257 256 258 257 static ssize_t sel_read_policyvers(struct file *filp, char __user *buf, ··· 268 265 269 266 static const struct file_operations sel_policyvers_ops = { 270 267 .read = sel_read_policyvers, 268 + .llseek = generic_file_llseek, 271 269 }; 272 270 273 271 /* declaration for sel_write_load */ ··· 293 289 294 290 static const struct file_operations sel_mls_ops = { 295 291 .read = sel_read_mls, 292 + .llseek = generic_file_llseek, 296 293 }; 297 294 298 295 static ssize_t sel_write_load(struct file *file, const char __user *buf, ··· 361 356 362 357 static const struct file_operations sel_load_ops = { 363 358 .write = sel_write_load, 359 + .llseek = generic_file_llseek, 364 360 }; 365 361 366 362 static ssize_t sel_write_context(struct file *file, char *buf, size_t size) ··· 443 437 static const struct file_operations sel_checkreqprot_ops = { 444 438 .read = sel_read_checkreqprot, 445 439 .write = sel_write_checkreqprot, 440 + .llseek = generic_file_llseek, 446 441 }; 447 442 448 443 /* ··· 489 482 .write = selinux_transaction_write, 490 483 .read = simple_transaction_read, 491 484 .release = simple_transaction_release, 485 + .llseek = generic_file_llseek, 492 486 }; 493 487 494 488 /* ··· 891 883 static const struct file_operations sel_bool_ops = { 892 884 .read = sel_read_bool, 893 885 .write = sel_write_bool, 886 + .llseek = generic_file_llseek, 894 887 }; 895 888 896 889 static ssize_t sel_commit_bools_write(struct file *filep, ··· 944 935 945 936 static const struct file_operations sel_commit_bools_ops = { 946 937 .write = sel_commit_bools_write, 938 + .llseek = generic_file_llseek, 947 939 }; 948 940 949 941 static void sel_remove_entries(struct dentry *de) ··· 1137 1127 static const struct file_operations sel_avc_cache_threshold_ops = { 1138 1128 .read = sel_read_avc_cache_threshold, 1139 1129 .write = sel_write_avc_cache_threshold, 1130 + .llseek = generic_file_llseek, 1140 1131 }; 1141 1132 1142 1133 static const struct file_operations sel_avc_hash_stats_ops = { 1143 1134 .read = sel_read_avc_hash_stats, 1135 + .llseek = generic_file_llseek, 1144 1136 }; 1145 1137 1146 1138 #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS ··· 1267 1255 1268 1256 static const struct file_operations sel_initcon_ops = { 1269 1257 .read = sel_read_initcon, 1258 + .llseek = generic_file_llseek, 1270 1259 }; 1271 1260 1272 1261 static int sel_make_initcon_files(struct dentry *dir) ··· 1343 1330 1344 1331 static const struct file_operations sel_class_ops = { 1345 1332 .read = sel_read_class, 1333 + .llseek = generic_file_llseek, 1346 1334 }; 1347 1335 1348 1336 static ssize_t sel_read_perm(struct file *file, char __user *buf, ··· 1368 1354 1369 1355 static const struct file_operations sel_perm_ops = { 1370 1356 .read = sel_read_perm, 1357 + .llseek = generic_file_llseek, 1371 1358 }; 1372 1359 1373 1360 static ssize_t sel_read_policycap(struct file *file, char __user *buf, ··· 1387 1372 1388 1373 static const struct file_operations sel_policycap_ops = { 1389 1374 .read = sel_read_policycap, 1375 + .llseek = generic_file_llseek, 1390 1376 }; 1391 1377 1392 1378 static int sel_make_perm_files(char *objclass, int classvalue,
+19 -20
security/selinux/ss/avtab.c
··· 342 342 343 343 if (vers < POLICYDB_VERSION_AVTAB) { 344 344 rc = next_entry(buf32, fp, sizeof(u32)); 345 - if (rc < 0) { 345 + if (rc) { 346 346 printk(KERN_ERR "SELinux: avtab: truncated entry\n"); 347 - return -1; 347 + return rc; 348 348 } 349 349 items2 = le32_to_cpu(buf32[0]); 350 350 if (items2 > ARRAY_SIZE(buf32)) { 351 351 printk(KERN_ERR "SELinux: avtab: entry overflow\n"); 352 - return -1; 352 + return -EINVAL; 353 353 354 354 } 355 355 rc = next_entry(buf32, fp, sizeof(u32)*items2); 356 - if (rc < 0) { 356 + if (rc) { 357 357 printk(KERN_ERR "SELinux: avtab: truncated entry\n"); 358 - return -1; 358 + return rc; 359 359 } 360 360 items = 0; 361 361 ··· 363 363 key.source_type = (u16)val; 364 364 if (key.source_type != val) { 365 365 printk(KERN_ERR "SELinux: avtab: truncated source type\n"); 366 - return -1; 366 + return -EINVAL; 367 367 } 368 368 val = le32_to_cpu(buf32[items++]); 369 369 key.target_type = (u16)val; 370 370 if (key.target_type != val) { 371 371 printk(KERN_ERR "SELinux: avtab: truncated target type\n"); 372 - return -1; 372 + return -EINVAL; 373 373 } 374 374 val = le32_to_cpu(buf32[items++]); 375 375 key.target_class = (u16)val; 376 376 if (key.target_class != val) { 377 377 printk(KERN_ERR "SELinux: avtab: truncated target class\n"); 378 - return -1; 378 + return -EINVAL; 379 379 } 380 380 381 381 val = le32_to_cpu(buf32[items++]); ··· 383 383 384 384 if (!(val & (AVTAB_AV | AVTAB_TYPE))) { 385 385 printk(KERN_ERR "SELinux: avtab: null entry\n"); 386 - return -1; 386 + return -EINVAL; 387 387 } 388 388 if ((val & AVTAB_AV) && 389 389 (val & AVTAB_TYPE)) { 390 390 printk(KERN_ERR "SELinux: avtab: entry has both access vectors and types\n"); 391 - return -1; 391 + return -EINVAL; 392 392 } 393 393 394 394 for (i = 0; i < ARRAY_SIZE(spec_order); i++) { ··· 403 403 404 404 if (items != items2) { 405 405 printk(KERN_ERR "SELinux: avtab: entry only had %d items, expected %d\n", items2, items); 406 - return -1; 406 + return -EINVAL; 407 407 } 408 408 return 0; 409 409 } 410 410 411 411 rc = next_entry(buf16, fp, sizeof(u16)*4); 412 - if (rc < 0) { 412 + if (rc) { 413 413 printk(KERN_ERR "SELinux: avtab: truncated entry\n"); 414 - return -1; 414 + return rc; 415 415 } 416 416 417 417 items = 0; ··· 424 424 !policydb_type_isvalid(pol, key.target_type) || 425 425 !policydb_class_isvalid(pol, key.target_class)) { 426 426 printk(KERN_ERR "SELinux: avtab: invalid type or class\n"); 427 - return -1; 427 + return -EINVAL; 428 428 } 429 429 430 430 set = 0; ··· 434 434 } 435 435 if (!set || set > 1) { 436 436 printk(KERN_ERR "SELinux: avtab: more than one specifier\n"); 437 - return -1; 437 + return -EINVAL; 438 438 } 439 439 440 440 rc = next_entry(buf32, fp, sizeof(u32)); 441 - if (rc < 0) { 441 + if (rc) { 442 442 printk(KERN_ERR "SELinux: avtab: truncated entry\n"); 443 - return -1; 443 + return rc; 444 444 } 445 445 datum.data = le32_to_cpu(*buf32); 446 446 if ((key.specified & AVTAB_TYPE) && 447 447 !policydb_type_isvalid(pol, datum.data)) { 448 448 printk(KERN_ERR "SELinux: avtab: invalid type\n"); 449 - return -1; 449 + return -EINVAL; 450 450 } 451 451 return insertf(a, &key, &datum, p); 452 452 } ··· 487 487 printk(KERN_ERR "SELinux: avtab: out of memory\n"); 488 488 else if (rc == -EEXIST) 489 489 printk(KERN_ERR "SELinux: avtab: duplicate entry\n"); 490 - else 491 - rc = -EINVAL; 490 + 492 491 goto bad; 493 492 } 494 493 }
+40 -25
security/selinux/ss/conditional.c
··· 117 117 118 118 int cond_policydb_init(struct policydb *p) 119 119 { 120 + int rc; 121 + 120 122 p->bool_val_to_struct = NULL; 121 123 p->cond_list = NULL; 122 - if (avtab_init(&p->te_cond_avtab)) 123 - return -1; 124 + 125 + rc = avtab_init(&p->te_cond_avtab); 126 + if (rc) 127 + return rc; 124 128 125 129 return 0; 126 130 } ··· 223 219 224 220 booldatum = kzalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); 225 221 if (!booldatum) 226 - return -1; 222 + return -ENOMEM; 227 223 228 224 rc = next_entry(buf, fp, sizeof buf); 229 - if (rc < 0) 225 + if (rc) 230 226 goto err; 231 227 232 228 booldatum->value = le32_to_cpu(buf[0]); 233 229 booldatum->state = le32_to_cpu(buf[1]); 234 230 231 + rc = -EINVAL; 235 232 if (!bool_isvalid(booldatum)) 236 233 goto err; 237 234 238 235 len = le32_to_cpu(buf[2]); 239 236 237 + rc = -ENOMEM; 240 238 key = kmalloc(len + 1, GFP_KERNEL); 241 239 if (!key) 242 240 goto err; 243 241 rc = next_entry(key, fp, len); 244 - if (rc < 0) 242 + if (rc) 245 243 goto err; 246 244 key[len] = '\0'; 247 - if (hashtab_insert(h, key, booldatum)) 245 + rc = hashtab_insert(h, key, booldatum); 246 + if (rc) 248 247 goto err; 249 248 250 249 return 0; 251 250 err: 252 251 cond_destroy_bool(key, booldatum, NULL); 253 - return -1; 252 + return rc; 254 253 } 255 254 256 255 struct cond_insertf_data { ··· 270 263 struct cond_av_list *other = data->other, *list, *cur; 271 264 struct avtab_node *node_ptr; 272 265 u8 found; 273 - 266 + int rc = -EINVAL; 274 267 275 268 /* 276 269 * For type rules we have to make certain there aren't any ··· 320 313 node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); 321 314 if (!node_ptr) { 322 315 printk(KERN_ERR "SELinux: could not insert rule.\n"); 316 + rc = -ENOMEM; 323 317 goto err; 324 318 } 325 319 326 320 list = kzalloc(sizeof(struct cond_av_list), GFP_KERNEL); 327 - if (!list) 321 + if (!list) { 322 + rc = -ENOMEM; 328 323 goto err; 324 + } 329 325 330 326 list->node = node_ptr; 331 327 if (!data->head) ··· 341 331 err: 342 332 cond_av_list_destroy(data->head); 343 333 data->head = NULL; 344 - return -1; 334 + return rc; 345 335 } 346 336 347 337 static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other) ··· 355 345 356 346 len = 0; 357 347 rc = next_entry(buf, fp, sizeof(u32)); 358 - if (rc < 0) 359 - return -1; 348 + if (rc) 349 + return rc; 360 350 361 351 len = le32_to_cpu(buf[0]); 362 352 if (len == 0) ··· 371 361 &data); 372 362 if (rc) 373 363 return rc; 374 - 375 364 } 376 365 377 366 *ret_list = data.head; ··· 399 390 struct cond_expr *expr = NULL, *last = NULL; 400 391 401 392 rc = next_entry(buf, fp, sizeof(u32)); 402 - if (rc < 0) 403 - return -1; 393 + if (rc) 394 + return rc; 404 395 405 396 node->cur_state = le32_to_cpu(buf[0]); 406 397 407 398 len = 0; 408 399 rc = next_entry(buf, fp, sizeof(u32)); 409 - if (rc < 0) 410 - return -1; 400 + if (rc) 401 + return rc; 411 402 412 403 /* expr */ 413 404 len = le32_to_cpu(buf[0]); 414 405 415 406 for (i = 0; i < len; i++) { 416 407 rc = next_entry(buf, fp, sizeof(u32) * 2); 417 - if (rc < 0) 408 + if (rc) 418 409 goto err; 419 410 411 + rc = -ENOMEM; 420 412 expr = kzalloc(sizeof(struct cond_expr), GFP_KERNEL); 421 413 if (!expr) 422 414 goto err; ··· 426 416 expr->bool = le32_to_cpu(buf[1]); 427 417 428 418 if (!expr_isvalid(p, expr)) { 419 + rc = -EINVAL; 429 420 kfree(expr); 430 421 goto err; 431 422 } ··· 438 427 last = expr; 439 428 } 440 429 441 - if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0) 430 + rc = cond_read_av_list(p, fp, &node->true_list, NULL); 431 + if (rc) 442 432 goto err; 443 - if (cond_read_av_list(p, fp, &node->false_list, node->true_list) != 0) 433 + rc = cond_read_av_list(p, fp, &node->false_list, node->true_list); 434 + if (rc) 444 435 goto err; 445 436 return 0; 446 437 err: 447 438 cond_node_destroy(node); 448 - return -1; 439 + return rc; 449 440 } 450 441 451 442 int cond_read_list(struct policydb *p, void *fp) ··· 458 445 int rc; 459 446 460 447 rc = next_entry(buf, fp, sizeof buf); 461 - if (rc < 0) 462 - return -1; 448 + if (rc) 449 + return rc; 463 450 464 451 len = le32_to_cpu(buf[0]); 465 452 ··· 468 455 goto err; 469 456 470 457 for (i = 0; i < len; i++) { 458 + rc = -ENOMEM; 471 459 node = kzalloc(sizeof(struct cond_node), GFP_KERNEL); 472 460 if (!node) 473 461 goto err; 474 462 475 - if (cond_read_node(p, node, fp) != 0) 463 + rc = cond_read_node(p, node, fp); 464 + if (rc) 476 465 goto err; 477 466 478 467 if (i == 0) ··· 487 472 err: 488 473 cond_list_destroy(p->cond_list); 489 474 p->cond_list = NULL; 490 - return -1; 475 + return rc; 491 476 } 492 477 493 478 /* Determine whether additional permissions are granted by the conditional
+370 -288
security/selinux/ss/policydb.c
··· 31 31 #include <linux/string.h> 32 32 #include <linux/errno.h> 33 33 #include <linux/audit.h> 34 + #include <linux/flex_array.h> 34 35 #include "security.h" 35 36 36 37 #include "policydb.h" ··· 656 655 657 656 static void ocontext_destroy(struct ocontext *c, int i) 658 657 { 658 + if (!c) 659 + return; 660 + 659 661 context_destroy(&c->context[0]); 660 662 context_destroy(&c->context[1]); 661 663 if (i == OCON_ISID || i == OCON_FS || ··· 740 736 hashtab_map(p->range_tr, range_tr_destroy, NULL); 741 737 hashtab_destroy(p->range_tr); 742 738 743 - if (p->type_attr_map) { 744 - for (i = 0; i < p->p_types.nprim; i++) 745 - ebitmap_destroy(&p->type_attr_map[i]); 739 + if (p->type_attr_map_array) { 740 + for (i = 0; i < p->p_types.nprim; i++) { 741 + struct ebitmap *e; 742 + 743 + e = flex_array_get(p->type_attr_map_array, i); 744 + if (!e) 745 + continue; 746 + ebitmap_destroy(e); 747 + } 748 + flex_array_free(p->type_attr_map_array); 746 749 } 747 - kfree(p->type_attr_map); 748 750 ebitmap_destroy(&p->policycaps); 749 751 ebitmap_destroy(&p->permissive_map); 750 752 ··· 1711 1701 return 1U << (perdatum->value-1); 1712 1702 } 1713 1703 1704 + static int range_read(struct policydb *p, void *fp) 1705 + { 1706 + struct range_trans *rt = NULL; 1707 + struct mls_range *r = NULL; 1708 + int i, rc; 1709 + __le32 buf[2]; 1710 + u32 nel; 1711 + 1712 + if (p->policyvers < POLICYDB_VERSION_MLS) 1713 + return 0; 1714 + 1715 + rc = next_entry(buf, fp, sizeof(u32)); 1716 + if (rc) 1717 + goto out; 1718 + 1719 + nel = le32_to_cpu(buf[0]); 1720 + for (i = 0; i < nel; i++) { 1721 + rc = -ENOMEM; 1722 + rt = kzalloc(sizeof(*rt), GFP_KERNEL); 1723 + if (!rt) 1724 + goto out; 1725 + 1726 + rc = next_entry(buf, fp, (sizeof(u32) * 2)); 1727 + if (rc) 1728 + goto out; 1729 + 1730 + rt->source_type = le32_to_cpu(buf[0]); 1731 + rt->target_type = le32_to_cpu(buf[1]); 1732 + if (p->policyvers >= POLICYDB_VERSION_RANGETRANS) { 1733 + rc = next_entry(buf, fp, sizeof(u32)); 1734 + if (rc) 1735 + goto out; 1736 + rt->target_class = le32_to_cpu(buf[0]); 1737 + } else 1738 + rt->target_class = p->process_class; 1739 + 1740 + rc = -EINVAL; 1741 + if (!policydb_type_isvalid(p, rt->source_type) || 1742 + !policydb_type_isvalid(p, rt->target_type) || 1743 + !policydb_class_isvalid(p, rt->target_class)) 1744 + goto out; 1745 + 1746 + rc = -ENOMEM; 1747 + r = kzalloc(sizeof(*r), GFP_KERNEL); 1748 + if (!r) 1749 + goto out; 1750 + 1751 + rc = mls_read_range_helper(r, fp); 1752 + if (rc) 1753 + goto out; 1754 + 1755 + rc = -EINVAL; 1756 + if (!mls_range_isvalid(p, r)) { 1757 + printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); 1758 + goto out; 1759 + } 1760 + 1761 + rc = hashtab_insert(p->range_tr, rt, r); 1762 + if (rc) 1763 + goto out; 1764 + 1765 + rt = NULL; 1766 + r = NULL; 1767 + } 1768 + rangetr_hash_eval(p->range_tr); 1769 + rc = 0; 1770 + out: 1771 + kfree(rt); 1772 + kfree(r); 1773 + return rc; 1774 + } 1775 + 1776 + static int genfs_read(struct policydb *p, void *fp) 1777 + { 1778 + int i, j, rc; 1779 + u32 nel, nel2, len, len2; 1780 + __le32 buf[1]; 1781 + struct ocontext *l, *c; 1782 + struct ocontext *newc = NULL; 1783 + struct genfs *genfs_p, *genfs; 1784 + struct genfs *newgenfs = NULL; 1785 + 1786 + rc = next_entry(buf, fp, sizeof(u32)); 1787 + if (rc) 1788 + goto out; 1789 + nel = le32_to_cpu(buf[0]); 1790 + 1791 + for (i = 0; i < nel; i++) { 1792 + rc = next_entry(buf, fp, sizeof(u32)); 1793 + if (rc) 1794 + goto out; 1795 + len = le32_to_cpu(buf[0]); 1796 + 1797 + rc = -ENOMEM; 1798 + newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL); 1799 + if (!newgenfs) 1800 + goto out; 1801 + 1802 + rc = -ENOMEM; 1803 + newgenfs->fstype = kmalloc(len + 1, GFP_KERNEL); 1804 + if (!newgenfs->fstype) 1805 + goto out; 1806 + 1807 + rc = next_entry(newgenfs->fstype, fp, len); 1808 + if (rc) 1809 + goto out; 1810 + 1811 + newgenfs->fstype[len] = 0; 1812 + 1813 + for (genfs_p = NULL, genfs = p->genfs; genfs; 1814 + genfs_p = genfs, genfs = genfs->next) { 1815 + rc = -EINVAL; 1816 + if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { 1817 + printk(KERN_ERR "SELinux: dup genfs fstype %s\n", 1818 + newgenfs->fstype); 1819 + goto out; 1820 + } 1821 + if (strcmp(newgenfs->fstype, genfs->fstype) < 0) 1822 + break; 1823 + } 1824 + newgenfs->next = genfs; 1825 + if (genfs_p) 1826 + genfs_p->next = newgenfs; 1827 + else 1828 + p->genfs = newgenfs; 1829 + genfs = newgenfs; 1830 + newgenfs = NULL; 1831 + 1832 + rc = next_entry(buf, fp, sizeof(u32)); 1833 + if (rc) 1834 + goto out; 1835 + 1836 + nel2 = le32_to_cpu(buf[0]); 1837 + for (j = 0; j < nel2; j++) { 1838 + rc = next_entry(buf, fp, sizeof(u32)); 1839 + if (rc) 1840 + goto out; 1841 + len = le32_to_cpu(buf[0]); 1842 + 1843 + rc = -ENOMEM; 1844 + newc = kzalloc(sizeof(*newc), GFP_KERNEL); 1845 + if (!newc) 1846 + goto out; 1847 + 1848 + rc = -ENOMEM; 1849 + newc->u.name = kmalloc(len + 1, GFP_KERNEL); 1850 + if (!newc->u.name) 1851 + goto out; 1852 + 1853 + rc = next_entry(newc->u.name, fp, len); 1854 + if (rc) 1855 + goto out; 1856 + newc->u.name[len] = 0; 1857 + 1858 + rc = next_entry(buf, fp, sizeof(u32)); 1859 + if (rc) 1860 + goto out; 1861 + 1862 + newc->v.sclass = le32_to_cpu(buf[0]); 1863 + rc = context_read_and_validate(&newc->context[0], p, fp); 1864 + if (rc) 1865 + goto out; 1866 + 1867 + for (l = NULL, c = genfs->head; c; 1868 + l = c, c = c->next) { 1869 + rc = -EINVAL; 1870 + if (!strcmp(newc->u.name, c->u.name) && 1871 + (!c->v.sclass || !newc->v.sclass || 1872 + newc->v.sclass == c->v.sclass)) { 1873 + printk(KERN_ERR "SELinux: dup genfs entry (%s,%s)\n", 1874 + genfs->fstype, c->u.name); 1875 + goto out; 1876 + } 1877 + len = strlen(newc->u.name); 1878 + len2 = strlen(c->u.name); 1879 + if (len > len2) 1880 + break; 1881 + } 1882 + 1883 + newc->next = c; 1884 + if (l) 1885 + l->next = newc; 1886 + else 1887 + genfs->head = newc; 1888 + newc = NULL; 1889 + } 1890 + } 1891 + rc = 0; 1892 + out: 1893 + if (newgenfs) 1894 + kfree(newgenfs->fstype); 1895 + kfree(newgenfs); 1896 + ocontext_destroy(newc, OCON_FSUSE); 1897 + 1898 + return rc; 1899 + } 1900 + 1901 + static int ocontext_read(struct policydb *p, struct policydb_compat_info *info, 1902 + void *fp) 1903 + { 1904 + int i, j, rc; 1905 + u32 nel, len; 1906 + __le32 buf[3]; 1907 + struct ocontext *l, *c; 1908 + u32 nodebuf[8]; 1909 + 1910 + for (i = 0; i < info->ocon_num; i++) { 1911 + rc = next_entry(buf, fp, sizeof(u32)); 1912 + if (rc) 1913 + goto out; 1914 + nel = le32_to_cpu(buf[0]); 1915 + 1916 + l = NULL; 1917 + for (j = 0; j < nel; j++) { 1918 + rc = -ENOMEM; 1919 + c = kzalloc(sizeof(*c), GFP_KERNEL); 1920 + if (!c) 1921 + goto out; 1922 + if (l) 1923 + l->next = c; 1924 + else 1925 + p->ocontexts[i] = c; 1926 + l = c; 1927 + 1928 + switch (i) { 1929 + case OCON_ISID: 1930 + rc = next_entry(buf, fp, sizeof(u32)); 1931 + if (rc) 1932 + goto out; 1933 + 1934 + c->sid[0] = le32_to_cpu(buf[0]); 1935 + rc = context_read_and_validate(&c->context[0], p, fp); 1936 + if (rc) 1937 + goto out; 1938 + break; 1939 + case OCON_FS: 1940 + case OCON_NETIF: 1941 + rc = next_entry(buf, fp, sizeof(u32)); 1942 + if (rc) 1943 + goto out; 1944 + len = le32_to_cpu(buf[0]); 1945 + 1946 + rc = -ENOMEM; 1947 + c->u.name = kmalloc(len + 1, GFP_KERNEL); 1948 + if (!c->u.name) 1949 + goto out; 1950 + 1951 + rc = next_entry(c->u.name, fp, len); 1952 + if (rc) 1953 + goto out; 1954 + 1955 + c->u.name[len] = 0; 1956 + rc = context_read_and_validate(&c->context[0], p, fp); 1957 + if (rc) 1958 + goto out; 1959 + rc = context_read_and_validate(&c->context[1], p, fp); 1960 + if (rc) 1961 + goto out; 1962 + break; 1963 + case OCON_PORT: 1964 + rc = next_entry(buf, fp, sizeof(u32)*3); 1965 + if (rc) 1966 + goto out; 1967 + c->u.port.protocol = le32_to_cpu(buf[0]); 1968 + c->u.port.low_port = le32_to_cpu(buf[1]); 1969 + c->u.port.high_port = le32_to_cpu(buf[2]); 1970 + rc = context_read_and_validate(&c->context[0], p, fp); 1971 + if (rc) 1972 + goto out; 1973 + break; 1974 + case OCON_NODE: 1975 + rc = next_entry(nodebuf, fp, sizeof(u32) * 2); 1976 + if (rc) 1977 + goto out; 1978 + c->u.node.addr = nodebuf[0]; /* network order */ 1979 + c->u.node.mask = nodebuf[1]; /* network order */ 1980 + rc = context_read_and_validate(&c->context[0], p, fp); 1981 + if (rc) 1982 + goto out; 1983 + break; 1984 + case OCON_FSUSE: 1985 + rc = next_entry(buf, fp, sizeof(u32)*2); 1986 + if (rc) 1987 + goto out; 1988 + 1989 + rc = -EINVAL; 1990 + c->v.behavior = le32_to_cpu(buf[0]); 1991 + if (c->v.behavior > SECURITY_FS_USE_NONE) 1992 + goto out; 1993 + 1994 + rc = -ENOMEM; 1995 + len = le32_to_cpu(buf[1]); 1996 + c->u.name = kmalloc(len + 1, GFP_KERNEL); 1997 + if (!c->u.name) 1998 + goto out; 1999 + 2000 + rc = next_entry(c->u.name, fp, len); 2001 + if (rc) 2002 + goto out; 2003 + c->u.name[len] = 0; 2004 + rc = context_read_and_validate(&c->context[0], p, fp); 2005 + if (rc) 2006 + goto out; 2007 + break; 2008 + case OCON_NODE6: { 2009 + int k; 2010 + 2011 + rc = next_entry(nodebuf, fp, sizeof(u32) * 8); 2012 + if (rc) 2013 + goto out; 2014 + for (k = 0; k < 4; k++) 2015 + c->u.node6.addr[k] = nodebuf[k]; 2016 + for (k = 0; k < 4; k++) 2017 + c->u.node6.mask[k] = nodebuf[k+4]; 2018 + rc = context_read_and_validate(&c->context[0], p, fp); 2019 + if (rc) 2020 + goto out; 2021 + break; 2022 + } 2023 + } 2024 + } 2025 + } 2026 + rc = 0; 2027 + out: 2028 + return rc; 2029 + } 2030 + 1714 2031 /* 1715 2032 * Read the configuration data from a policy database binary 1716 2033 * representation file into a policy database structure. ··· 2046 1709 { 2047 1710 struct role_allow *ra, *lra; 2048 1711 struct role_trans *tr, *ltr; 2049 - struct ocontext *l, *c, *newc; 2050 - struct genfs *genfs_p, *genfs, *newgenfs; 2051 1712 int i, j, rc; 2052 1713 __le32 buf[4]; 2053 - u32 nodebuf[8]; 2054 - u32 len, len2, nprim, nel, nel2; 1714 + u32 len, nprim, nel; 1715 + 2055 1716 char *policydb_str; 2056 1717 struct policydb_compat_info *info; 2057 - struct range_trans *rt; 2058 - struct mls_range *r; 2059 1718 2060 1719 rc = policydb_init(p); 2061 1720 if (rc) ··· 2252 1919 if (!p->process_trans_perms) 2253 1920 goto bad; 2254 1921 2255 - for (i = 0; i < info->ocon_num; i++) { 2256 - rc = next_entry(buf, fp, sizeof(u32)); 2257 - if (rc < 0) 2258 - goto bad; 2259 - nel = le32_to_cpu(buf[0]); 2260 - l = NULL; 2261 - for (j = 0; j < nel; j++) { 2262 - c = kzalloc(sizeof(*c), GFP_KERNEL); 2263 - if (!c) { 2264 - rc = -ENOMEM; 2265 - goto bad; 2266 - } 2267 - if (l) 2268 - l->next = c; 2269 - else 2270 - p->ocontexts[i] = c; 2271 - l = c; 2272 - rc = -EINVAL; 2273 - switch (i) { 2274 - case OCON_ISID: 2275 - rc = next_entry(buf, fp, sizeof(u32)); 2276 - if (rc < 0) 2277 - goto bad; 2278 - c->sid[0] = le32_to_cpu(buf[0]); 2279 - rc = context_read_and_validate(&c->context[0], p, fp); 2280 - if (rc) 2281 - goto bad; 2282 - break; 2283 - case OCON_FS: 2284 - case OCON_NETIF: 2285 - rc = next_entry(buf, fp, sizeof(u32)); 2286 - if (rc < 0) 2287 - goto bad; 2288 - len = le32_to_cpu(buf[0]); 2289 - c->u.name = kmalloc(len + 1, GFP_KERNEL); 2290 - if (!c->u.name) { 2291 - rc = -ENOMEM; 2292 - goto bad; 2293 - } 2294 - rc = next_entry(c->u.name, fp, len); 2295 - if (rc < 0) 2296 - goto bad; 2297 - c->u.name[len] = 0; 2298 - rc = context_read_and_validate(&c->context[0], p, fp); 2299 - if (rc) 2300 - goto bad; 2301 - rc = context_read_and_validate(&c->context[1], p, fp); 2302 - if (rc) 2303 - goto bad; 2304 - break; 2305 - case OCON_PORT: 2306 - rc = next_entry(buf, fp, sizeof(u32)*3); 2307 - if (rc < 0) 2308 - goto bad; 2309 - c->u.port.protocol = le32_to_cpu(buf[0]); 2310 - c->u.port.low_port = le32_to_cpu(buf[1]); 2311 - c->u.port.high_port = le32_to_cpu(buf[2]); 2312 - rc = context_read_and_validate(&c->context[0], p, fp); 2313 - if (rc) 2314 - goto bad; 2315 - break; 2316 - case OCON_NODE: 2317 - rc = next_entry(nodebuf, fp, sizeof(u32) * 2); 2318 - if (rc < 0) 2319 - goto bad; 2320 - c->u.node.addr = nodebuf[0]; /* network order */ 2321 - c->u.node.mask = nodebuf[1]; /* network order */ 2322 - rc = context_read_and_validate(&c->context[0], p, fp); 2323 - if (rc) 2324 - goto bad; 2325 - break; 2326 - case OCON_FSUSE: 2327 - rc = next_entry(buf, fp, sizeof(u32)*2); 2328 - if (rc < 0) 2329 - goto bad; 2330 - c->v.behavior = le32_to_cpu(buf[0]); 2331 - if (c->v.behavior > SECURITY_FS_USE_NONE) 2332 - goto bad; 2333 - len = le32_to_cpu(buf[1]); 2334 - c->u.name = kmalloc(len + 1, GFP_KERNEL); 2335 - if (!c->u.name) { 2336 - rc = -ENOMEM; 2337 - goto bad; 2338 - } 2339 - rc = next_entry(c->u.name, fp, len); 2340 - if (rc < 0) 2341 - goto bad; 2342 - c->u.name[len] = 0; 2343 - rc = context_read_and_validate(&c->context[0], p, fp); 2344 - if (rc) 2345 - goto bad; 2346 - break; 2347 - case OCON_NODE6: { 2348 - int k; 2349 - 2350 - rc = next_entry(nodebuf, fp, sizeof(u32) * 8); 2351 - if (rc < 0) 2352 - goto bad; 2353 - for (k = 0; k < 4; k++) 2354 - c->u.node6.addr[k] = nodebuf[k]; 2355 - for (k = 0; k < 4; k++) 2356 - c->u.node6.mask[k] = nodebuf[k+4]; 2357 - if (context_read_and_validate(&c->context[0], p, fp)) 2358 - goto bad; 2359 - break; 2360 - } 2361 - } 2362 - } 2363 - } 2364 - 2365 - rc = next_entry(buf, fp, sizeof(u32)); 2366 - if (rc < 0) 1922 + rc = ocontext_read(p, info, fp); 1923 + if (rc) 2367 1924 goto bad; 2368 - nel = le32_to_cpu(buf[0]); 2369 - genfs_p = NULL; 2370 - rc = -EINVAL; 2371 - for (i = 0; i < nel; i++) { 2372 - rc = next_entry(buf, fp, sizeof(u32)); 2373 - if (rc < 0) 2374 - goto bad; 2375 - len = le32_to_cpu(buf[0]); 2376 - newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL); 2377 - if (!newgenfs) { 2378 - rc = -ENOMEM; 2379 - goto bad; 2380 - } 2381 1925 2382 - newgenfs->fstype = kmalloc(len + 1, GFP_KERNEL); 2383 - if (!newgenfs->fstype) { 2384 - rc = -ENOMEM; 2385 - kfree(newgenfs); 2386 - goto bad; 2387 - } 2388 - rc = next_entry(newgenfs->fstype, fp, len); 2389 - if (rc < 0) { 2390 - kfree(newgenfs->fstype); 2391 - kfree(newgenfs); 2392 - goto bad; 2393 - } 2394 - newgenfs->fstype[len] = 0; 2395 - for (genfs_p = NULL, genfs = p->genfs; genfs; 2396 - genfs_p = genfs, genfs = genfs->next) { 2397 - if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { 2398 - printk(KERN_ERR "SELinux: dup genfs " 2399 - "fstype %s\n", newgenfs->fstype); 2400 - kfree(newgenfs->fstype); 2401 - kfree(newgenfs); 2402 - goto bad; 2403 - } 2404 - if (strcmp(newgenfs->fstype, genfs->fstype) < 0) 2405 - break; 2406 - } 2407 - newgenfs->next = genfs; 2408 - if (genfs_p) 2409 - genfs_p->next = newgenfs; 2410 - else 2411 - p->genfs = newgenfs; 2412 - rc = next_entry(buf, fp, sizeof(u32)); 2413 - if (rc < 0) 2414 - goto bad; 2415 - nel2 = le32_to_cpu(buf[0]); 2416 - for (j = 0; j < nel2; j++) { 2417 - rc = next_entry(buf, fp, sizeof(u32)); 2418 - if (rc < 0) 2419 - goto bad; 2420 - len = le32_to_cpu(buf[0]); 1926 + rc = genfs_read(p, fp); 1927 + if (rc) 1928 + goto bad; 2421 1929 2422 - newc = kzalloc(sizeof(*newc), GFP_KERNEL); 2423 - if (!newc) { 2424 - rc = -ENOMEM; 2425 - goto bad; 2426 - } 1930 + rc = range_read(p, fp); 1931 + if (rc) 1932 + goto bad; 2427 1933 2428 - newc->u.name = kmalloc(len + 1, GFP_KERNEL); 2429 - if (!newc->u.name) { 2430 - rc = -ENOMEM; 2431 - goto bad_newc; 2432 - } 2433 - rc = next_entry(newc->u.name, fp, len); 2434 - if (rc < 0) 2435 - goto bad_newc; 2436 - newc->u.name[len] = 0; 2437 - rc = next_entry(buf, fp, sizeof(u32)); 2438 - if (rc < 0) 2439 - goto bad_newc; 2440 - newc->v.sclass = le32_to_cpu(buf[0]); 2441 - if (context_read_and_validate(&newc->context[0], p, fp)) 2442 - goto bad_newc; 2443 - for (l = NULL, c = newgenfs->head; c; 2444 - l = c, c = c->next) { 2445 - if (!strcmp(newc->u.name, c->u.name) && 2446 - (!c->v.sclass || !newc->v.sclass || 2447 - newc->v.sclass == c->v.sclass)) { 2448 - printk(KERN_ERR "SELinux: dup genfs " 2449 - "entry (%s,%s)\n", 2450 - newgenfs->fstype, c->u.name); 2451 - goto bad_newc; 2452 - } 2453 - len = strlen(newc->u.name); 2454 - len2 = strlen(c->u.name); 2455 - if (len > len2) 2456 - break; 2457 - } 1934 + rc = -ENOMEM; 1935 + p->type_attr_map_array = flex_array_alloc(sizeof(struct ebitmap), 1936 + p->p_types.nprim, 1937 + GFP_KERNEL | __GFP_ZERO); 1938 + if (!p->type_attr_map_array) 1939 + goto bad; 2458 1940 2459 - newc->next = c; 2460 - if (l) 2461 - l->next = newc; 2462 - else 2463 - newgenfs->head = newc; 2464 - } 2465 - } 2466 - 2467 - if (p->policyvers >= POLICYDB_VERSION_MLS) { 2468 - int new_rangetr = p->policyvers >= POLICYDB_VERSION_RANGETRANS; 2469 - rc = next_entry(buf, fp, sizeof(u32)); 2470 - if (rc < 0) 2471 - goto bad; 2472 - nel = le32_to_cpu(buf[0]); 2473 - for (i = 0; i < nel; i++) { 2474 - rt = kzalloc(sizeof(*rt), GFP_KERNEL); 2475 - if (!rt) { 2476 - rc = -ENOMEM; 2477 - goto bad; 2478 - } 2479 - rc = next_entry(buf, fp, (sizeof(u32) * 2)); 2480 - if (rc < 0) { 2481 - kfree(rt); 2482 - goto bad; 2483 - } 2484 - rt->source_type = le32_to_cpu(buf[0]); 2485 - rt->target_type = le32_to_cpu(buf[1]); 2486 - if (new_rangetr) { 2487 - rc = next_entry(buf, fp, sizeof(u32)); 2488 - if (rc < 0) { 2489 - kfree(rt); 2490 - goto bad; 2491 - } 2492 - rt->target_class = le32_to_cpu(buf[0]); 2493 - } else 2494 - rt->target_class = p->process_class; 2495 - if (!policydb_type_isvalid(p, rt->source_type) || 2496 - !policydb_type_isvalid(p, rt->target_type) || 2497 - !policydb_class_isvalid(p, rt->target_class)) { 2498 - kfree(rt); 2499 - rc = -EINVAL; 2500 - goto bad; 2501 - } 2502 - r = kzalloc(sizeof(*r), GFP_KERNEL); 2503 - if (!r) { 2504 - kfree(rt); 2505 - rc = -ENOMEM; 2506 - goto bad; 2507 - } 2508 - rc = mls_read_range_helper(r, fp); 2509 - if (rc) { 2510 - kfree(rt); 2511 - kfree(r); 2512 - goto bad; 2513 - } 2514 - if (!mls_range_isvalid(p, r)) { 2515 - printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); 2516 - kfree(rt); 2517 - kfree(r); 2518 - goto bad; 2519 - } 2520 - rc = hashtab_insert(p->range_tr, rt, r); 2521 - if (rc) { 2522 - kfree(rt); 2523 - kfree(r); 2524 - goto bad; 2525 - } 2526 - } 2527 - rangetr_hash_eval(p->range_tr); 2528 - } 2529 - 2530 - p->type_attr_map = kmalloc(p->p_types.nprim * sizeof(struct ebitmap), GFP_KERNEL); 2531 - if (!p->type_attr_map) 1941 + /* preallocate so we don't have to worry about the put ever failing */ 1942 + rc = flex_array_prealloc(p->type_attr_map_array, 0, p->p_types.nprim - 1, 1943 + GFP_KERNEL | __GFP_ZERO); 1944 + if (rc) 2532 1945 goto bad; 2533 1946 2534 1947 for (i = 0; i < p->p_types.nprim; i++) { 2535 - ebitmap_init(&p->type_attr_map[i]); 1948 + struct ebitmap *e = flex_array_get(p->type_attr_map_array, i); 1949 + 1950 + BUG_ON(!e); 1951 + ebitmap_init(e); 2536 1952 if (p->policyvers >= POLICYDB_VERSION_AVTAB) { 2537 - if (ebitmap_read(&p->type_attr_map[i], fp)) 1953 + rc = ebitmap_read(e, fp); 1954 + if (rc) 2538 1955 goto bad; 2539 1956 } 2540 1957 /* add the type itself as the degenerate case */ 2541 - if (ebitmap_set_bit(&p->type_attr_map[i], i, 1)) 2542 - goto bad; 1958 + rc = ebitmap_set_bit(e, i, 1); 1959 + if (rc) 1960 + goto bad; 2543 1961 } 2544 1962 2545 1963 rc = policydb_bounds_sanity_check(p); ··· 2300 2216 rc = 0; 2301 2217 out: 2302 2218 return rc; 2303 - bad_newc: 2304 - ocontext_destroy(newc, OCON_FSUSE); 2305 2219 bad: 2306 2220 if (!rc) 2307 2221 rc = -EINVAL;
+3 -1
security/selinux/ss/policydb.h
··· 24 24 #ifndef _SS_POLICYDB_H_ 25 25 #define _SS_POLICYDB_H_ 26 26 27 + #include <linux/flex_array.h> 28 + 27 29 #include "symtab.h" 28 30 #include "avtab.h" 29 31 #include "sidtab.h" ··· 248 246 struct hashtab *range_tr; 249 247 250 248 /* type -> attribute reverse mapping */ 251 - struct ebitmap *type_attr_map; 249 + struct flex_array *type_attr_map_array; 252 250 253 251 struct ebitmap policycaps; 254 252
+5 -2
security/selinux/ss/services.c
··· 50 50 #include <linux/audit.h> 51 51 #include <linux/mutex.h> 52 52 #include <linux/selinux.h> 53 + #include <linux/flex_array.h> 53 54 #include <net/netlabel.h> 54 55 55 56 #include "flask.h" ··· 627 626 */ 628 627 avkey.target_class = tclass; 629 628 avkey.specified = AVTAB_AV; 630 - sattr = &policydb.type_attr_map[scontext->type - 1]; 631 - tattr = &policydb.type_attr_map[tcontext->type - 1]; 629 + sattr = flex_array_get(policydb.type_attr_map_array, scontext->type - 1); 630 + BUG_ON(!sattr); 631 + tattr = flex_array_get(policydb.type_attr_map_array, tcontext->type - 1); 632 + BUG_ON(!tattr); 632 633 ebitmap_for_each_positive_bit(sattr, snode, i) { 633 634 ebitmap_for_each_positive_bit(tattr, tnode, j) { 634 635 avkey.source_type = i + 1;
+1 -1
security/selinux/ss/symtab.c
··· 36 36 { 37 37 s->table = hashtab_create(symhash, symcmp, size); 38 38 if (!s->table) 39 - return -1; 39 + return -ENOMEM; 40 40 s->nprim = 0; 41 41 return 0; 42 42 }
-10
security/smack/smack.h
··· 123 123 #define SMK_FSHAT "smackfshat=" 124 124 #define SMK_FSROOT "smackfsroot=" 125 125 126 - /* 127 - * xattr names 128 - */ 129 - #define XATTR_SMACK_SUFFIX "SMACK64" 130 - #define XATTR_SMACK_IPIN "SMACK64IPIN" 131 - #define XATTR_SMACK_IPOUT "SMACK64IPOUT" 132 - #define XATTR_NAME_SMACK XATTR_SECURITY_PREFIX XATTR_SMACK_SUFFIX 133 - #define XATTR_NAME_SMACKIPIN XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN 134 - #define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT 135 - 136 126 #define SMACK_CIPSO_OPTION "-CIPSO" 137 127 138 128 /*
+4 -12
security/smack/smack_lsm.c
··· 598 598 static int smack_inode_permission(struct inode *inode, int mask) 599 599 { 600 600 struct smk_audit_info ad; 601 + 602 + mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); 601 603 /* 602 604 * No permission to check. Existence test. Yup, it's there. 603 605 */ ··· 2193 2191 2194 2192 /** 2195 2193 * smack_d_instantiate - Make sure the blob is correct on an inode 2196 - * @opt_dentry: unused 2194 + * @opt_dentry: dentry where inode will be attached 2197 2195 * @inode: the object 2198 2196 * 2199 2197 * Set the inode's security blob if it hasn't been done already. ··· 2312 2310 /* 2313 2311 * Get the dentry for xattr. 2314 2312 */ 2315 - if (opt_dentry == NULL) { 2316 - dp = d_find_alias(inode); 2317 - if (dp == NULL) 2318 - break; 2319 - } else { 2320 - dp = dget(opt_dentry); 2321 - if (dp == NULL) 2322 - break; 2323 - } 2324 - 2313 + dp = dget(opt_dentry); 2325 2314 fetched = smk_fetch(inode, dp); 2326 2315 if (fetched != NULL) 2327 2316 final = fetched; 2328 - 2329 2317 dput(dp); 2330 2318 break; 2331 2319 }
+1 -1
security/tomoyo/Makefile
··· 1 - obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o path_group.o 1 + obj-y = common.o domain.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o
+1361 -1609
security/tomoyo/common.c
··· 3 3 * 4 4 * Common functions for TOMOYO. 5 5 * 6 - * Copyright (C) 2005-2009 NTT DATA CORPORATION 7 - * 8 - * Version: 2.2.0 2009/04/01 9 - * 6 + * Copyright (C) 2005-2010 NTT DATA CORPORATION 10 7 */ 11 8 12 9 #include <linux/uaccess.h> 13 10 #include <linux/slab.h> 14 11 #include <linux/security.h> 15 - #include <linux/hardirq.h> 16 12 #include "common.h" 17 13 18 - /* Lock for protecting policy. */ 19 - DEFINE_MUTEX(tomoyo_policy_lock); 14 + static struct tomoyo_profile tomoyo_default_profile = { 15 + .learning = &tomoyo_default_profile.preference, 16 + .permissive = &tomoyo_default_profile.preference, 17 + .enforcing = &tomoyo_default_profile.preference, 18 + .preference.enforcing_verbose = true, 19 + .preference.learning_max_entry = 2048, 20 + .preference.learning_verbose = false, 21 + .preference.permissive_verbose = true 22 + }; 20 23 21 - /* Has loading policy done? */ 22 - bool tomoyo_policy_loaded; 24 + /* Profile version. Currently only 20090903 is defined. */ 25 + static unsigned int tomoyo_profile_version; 26 + 27 + /* Profile table. Memory is allocated as needed. */ 28 + static struct tomoyo_profile *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES]; 23 29 24 30 /* String table for functionality that takes 4 modes. */ 25 - static const char *tomoyo_mode_4[4] = { 31 + static const char *tomoyo_mode[4] = { 26 32 "disabled", "learning", "permissive", "enforcing" 27 33 }; 28 - /* String table for functionality that takes 2 modes. */ 29 - static const char *tomoyo_mode_2[4] = { 30 - "disabled", "enabled", "enabled", "enabled" 31 - }; 32 34 33 - /* 34 - * tomoyo_control_array is a static data which contains 35 - * 36 - * (1) functionality name used by /sys/kernel/security/tomoyo/profile . 37 - * (2) initial values for "struct tomoyo_profile". 38 - * (3) max values for "struct tomoyo_profile". 39 - */ 40 - static struct { 41 - const char *keyword; 42 - unsigned int current_value; 43 - const unsigned int max_value; 44 - } tomoyo_control_array[TOMOYO_MAX_CONTROL_INDEX] = { 45 - [TOMOYO_MAC_FOR_FILE] = { "MAC_FOR_FILE", 0, 3 }, 46 - [TOMOYO_MAX_ACCEPT_ENTRY] = { "MAX_ACCEPT_ENTRY", 2048, INT_MAX }, 47 - [TOMOYO_VERBOSE] = { "TOMOYO_VERBOSE", 1, 1 }, 35 + /* String table for /sys/kernel/security/tomoyo/profile */ 36 + static const char *tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX 37 + + TOMOYO_MAX_MAC_CATEGORY_INDEX] = { 38 + [TOMOYO_MAC_FILE_EXECUTE] = "file::execute", 39 + [TOMOYO_MAC_FILE_OPEN] = "file::open", 40 + [TOMOYO_MAC_FILE_CREATE] = "file::create", 41 + [TOMOYO_MAC_FILE_UNLINK] = "file::unlink", 42 + [TOMOYO_MAC_FILE_MKDIR] = "file::mkdir", 43 + [TOMOYO_MAC_FILE_RMDIR] = "file::rmdir", 44 + [TOMOYO_MAC_FILE_MKFIFO] = "file::mkfifo", 45 + [TOMOYO_MAC_FILE_MKSOCK] = "file::mksock", 46 + [TOMOYO_MAC_FILE_TRUNCATE] = "file::truncate", 47 + [TOMOYO_MAC_FILE_SYMLINK] = "file::symlink", 48 + [TOMOYO_MAC_FILE_REWRITE] = "file::rewrite", 49 + [TOMOYO_MAC_FILE_MKBLOCK] = "file::mkblock", 50 + [TOMOYO_MAC_FILE_MKCHAR] = "file::mkchar", 51 + [TOMOYO_MAC_FILE_LINK] = "file::link", 52 + [TOMOYO_MAC_FILE_RENAME] = "file::rename", 53 + [TOMOYO_MAC_FILE_CHMOD] = "file::chmod", 54 + [TOMOYO_MAC_FILE_CHOWN] = "file::chown", 55 + [TOMOYO_MAC_FILE_CHGRP] = "file::chgrp", 56 + [TOMOYO_MAC_FILE_IOCTL] = "file::ioctl", 57 + [TOMOYO_MAC_FILE_CHROOT] = "file::chroot", 58 + [TOMOYO_MAC_FILE_MOUNT] = "file::mount", 59 + [TOMOYO_MAC_FILE_UMOUNT] = "file::umount", 60 + [TOMOYO_MAC_FILE_PIVOT_ROOT] = "file::pivot_root", 61 + [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file", 48 62 }; 49 - 50 - /* 51 - * tomoyo_profile is a structure which is used for holding the mode of access 52 - * controls. TOMOYO has 4 modes: disabled, learning, permissive, enforcing. 53 - * An administrator can define up to 256 profiles. 54 - * The ->profile of "struct tomoyo_domain_info" is used for remembering 55 - * the profile's number (0 - 255) assigned to that domain. 56 - */ 57 - static struct tomoyo_profile { 58 - unsigned int value[TOMOYO_MAX_CONTROL_INDEX]; 59 - const struct tomoyo_path_info *comment; 60 - } *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES]; 61 63 62 64 /* Permit policy management by non-root user? */ 63 65 static bool tomoyo_manage_by_non_root; 64 66 65 67 /* Utility functions. */ 66 68 67 - /* Open operation for /sys/kernel/security/tomoyo/ interface. */ 68 - static int tomoyo_open_control(const u8 type, struct file *file); 69 - /* Close /sys/kernel/security/tomoyo/ interface. */ 70 - static int tomoyo_close_control(struct file *file); 71 - /* Read operation for /sys/kernel/security/tomoyo/ interface. */ 72 - static int tomoyo_read_control(struct file *file, char __user *buffer, 73 - const int buffer_len); 74 - /* Write operation for /sys/kernel/security/tomoyo/ interface. */ 75 - static int tomoyo_write_control(struct file *file, const char __user *buffer, 76 - const int buffer_len); 69 + /** 70 + * tomoyo_yesno - Return "yes" or "no". 71 + * 72 + * @value: Bool value. 73 + */ 74 + static const char *tomoyo_yesno(const unsigned int value) 75 + { 76 + return value ? "yes" : "no"; 77 + } 78 + 79 + static void tomoyo_addprintf(char *buffer, int len, const char *fmt, ...) 80 + { 81 + va_list args; 82 + const int pos = strlen(buffer); 83 + va_start(args, fmt); 84 + vsnprintf(buffer + pos, len - pos - 1, fmt, args); 85 + va_end(args); 86 + } 77 87 78 88 /** 79 - * tomoyo_parse_name_union - Parse a tomoyo_name_union. 89 + * tomoyo_flush - Flush queued string to userspace's buffer. 80 90 * 81 - * @filename: Name or name group. 82 - * @ptr: Pointer to "struct tomoyo_name_union". 91 + * @head: Pointer to "struct tomoyo_io_buffer". 83 92 * 84 - * Returns true on success, false otherwise. 93 + * Returns true if all data was flushed, false otherwise. 85 94 */ 86 - bool tomoyo_parse_name_union(const char *filename, 87 - struct tomoyo_name_union *ptr) 95 + static bool tomoyo_flush(struct tomoyo_io_buffer *head) 88 96 { 89 - if (!tomoyo_is_correct_path(filename, 0, 0, 0)) 90 - return false; 91 - if (filename[0] == '@') { 92 - ptr->group = tomoyo_get_path_group(filename + 1); 93 - ptr->is_group = true; 94 - return ptr->group != NULL; 97 + while (head->r.w_pos) { 98 + const char *w = head->r.w[0]; 99 + int len = strlen(w); 100 + if (len) { 101 + if (len > head->read_user_buf_avail) 102 + len = head->read_user_buf_avail; 103 + if (!len) 104 + return false; 105 + if (copy_to_user(head->read_user_buf, w, len)) 106 + return false; 107 + head->read_user_buf_avail -= len; 108 + head->read_user_buf += len; 109 + w += len; 110 + } 111 + if (*w) { 112 + head->r.w[0] = w; 113 + return false; 114 + } 115 + /* Add '\0' for query. */ 116 + if (head->poll) { 117 + if (!head->read_user_buf_avail || 118 + copy_to_user(head->read_user_buf, "", 1)) 119 + return false; 120 + head->read_user_buf_avail--; 121 + head->read_user_buf++; 122 + } 123 + head->r.w_pos--; 124 + for (len = 0; len < head->r.w_pos; len++) 125 + head->r.w[len] = head->r.w[len + 1]; 95 126 } 96 - ptr->filename = tomoyo_get_name(filename); 97 - ptr->is_group = false; 98 - return ptr->filename != NULL; 127 + head->r.avail = 0; 128 + return true; 129 + } 130 + 131 + /** 132 + * tomoyo_set_string - Queue string to "struct tomoyo_io_buffer" structure. 133 + * 134 + * @head: Pointer to "struct tomoyo_io_buffer". 135 + * @string: String to print. 136 + * 137 + * Note that @string has to be kept valid until @head is kfree()d. 138 + * This means that char[] allocated on stack memory cannot be passed to 139 + * this function. Use tomoyo_io_printf() for char[] allocated on stack memory. 140 + */ 141 + static void tomoyo_set_string(struct tomoyo_io_buffer *head, const char *string) 142 + { 143 + if (head->r.w_pos < TOMOYO_MAX_IO_READ_QUEUE) { 144 + head->r.w[head->r.w_pos++] = string; 145 + tomoyo_flush(head); 146 + } else 147 + WARN_ON(1); 148 + } 149 + 150 + /** 151 + * tomoyo_io_printf - printf() to "struct tomoyo_io_buffer" structure. 152 + * 153 + * @head: Pointer to "struct tomoyo_io_buffer". 154 + * @fmt: The printf()'s format string, followed by parameters. 155 + */ 156 + void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) 157 + { 158 + va_list args; 159 + int len; 160 + int pos = head->r.avail; 161 + int size = head->readbuf_size - pos; 162 + if (size <= 0) 163 + return; 164 + va_start(args, fmt); 165 + len = vsnprintf(head->read_buf + pos, size, fmt, args) + 1; 166 + va_end(args); 167 + if (pos + len >= head->readbuf_size) { 168 + WARN_ON(1); 169 + return; 170 + } 171 + head->r.avail += len; 172 + tomoyo_set_string(head, head->read_buf + pos); 173 + } 174 + 175 + static void tomoyo_set_space(struct tomoyo_io_buffer *head) 176 + { 177 + tomoyo_set_string(head, " "); 178 + } 179 + 180 + static bool tomoyo_set_lf(struct tomoyo_io_buffer *head) 181 + { 182 + tomoyo_set_string(head, "\n"); 183 + return !head->r.w_pos; 99 184 } 100 185 101 186 /** ··· 188 103 * 189 104 * @head: Pointer to "struct tomoyo_io_buffer". 190 105 * @ptr: Pointer to "struct tomoyo_name_union". 191 - * 192 - * Returns true on success, false otherwise. 193 106 */ 194 - static bool tomoyo_print_name_union(struct tomoyo_io_buffer *head, 195 - const struct tomoyo_name_union *ptr) 107 + static void tomoyo_print_name_union(struct tomoyo_io_buffer *head, 108 + const struct tomoyo_name_union *ptr) 196 109 { 197 - int pos = head->read_avail; 198 - if (pos && head->read_buf[pos - 1] == ' ') 199 - head->read_avail--; 200 - if (ptr->is_group) 201 - return tomoyo_io_printf(head, " @%s", 202 - ptr->group->group_name->name); 203 - return tomoyo_io_printf(head, " %s", ptr->filename->name); 204 - } 205 - 206 - /** 207 - * tomoyo_is_byte_range - Check whether the string isa \ooo style octal value. 208 - * 209 - * @str: Pointer to the string. 210 - * 211 - * Returns true if @str is a \ooo style octal value, false otherwise. 212 - * 213 - * TOMOYO uses \ooo style representation for 0x01 - 0x20 and 0x7F - 0xFF. 214 - * This function verifies that \ooo is in valid range. 215 - */ 216 - static inline bool tomoyo_is_byte_range(const char *str) 217 - { 218 - return *str >= '0' && *str++ <= '3' && 219 - *str >= '0' && *str++ <= '7' && 220 - *str >= '0' && *str <= '7'; 221 - } 222 - 223 - /** 224 - * tomoyo_is_alphabet_char - Check whether the character is an alphabet. 225 - * 226 - * @c: The character to check. 227 - * 228 - * Returns true if @c is an alphabet character, false otherwise. 229 - */ 230 - static inline bool tomoyo_is_alphabet_char(const char c) 231 - { 232 - return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); 233 - } 234 - 235 - /** 236 - * tomoyo_make_byte - Make byte value from three octal characters. 237 - * 238 - * @c1: The first character. 239 - * @c2: The second character. 240 - * @c3: The third character. 241 - * 242 - * Returns byte value. 243 - */ 244 - static inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3) 245 - { 246 - return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0'); 247 - } 248 - 249 - /** 250 - * tomoyo_str_starts - Check whether the given string starts with the given keyword. 251 - * 252 - * @src: Pointer to pointer to the string. 253 - * @find: Pointer to the keyword. 254 - * 255 - * Returns true if @src starts with @find, false otherwise. 256 - * 257 - * The @src is updated to point the first character after the @find 258 - * if @src starts with @find. 259 - */ 260 - static bool tomoyo_str_starts(char **src, const char *find) 261 - { 262 - const int len = strlen(find); 263 - char *tmp = *src; 264 - 265 - if (strncmp(tmp, find, len)) 266 - return false; 267 - tmp += len; 268 - *src = tmp; 269 - return true; 270 - } 271 - 272 - /** 273 - * tomoyo_normalize_line - Format string. 274 - * 275 - * @buffer: The line to normalize. 276 - * 277 - * Leading and trailing whitespaces are removed. 278 - * Multiple whitespaces are packed into single space. 279 - * 280 - * Returns nothing. 281 - */ 282 - static void tomoyo_normalize_line(unsigned char *buffer) 283 - { 284 - unsigned char *sp = buffer; 285 - unsigned char *dp = buffer; 286 - bool first = true; 287 - 288 - while (tomoyo_is_invalid(*sp)) 289 - sp++; 290 - while (*sp) { 291 - if (!first) 292 - *dp++ = ' '; 293 - first = false; 294 - while (tomoyo_is_valid(*sp)) 295 - *dp++ = *sp++; 296 - while (tomoyo_is_invalid(*sp)) 297 - sp++; 110 + tomoyo_set_space(head); 111 + if (ptr->is_group) { 112 + tomoyo_set_string(head, "@"); 113 + tomoyo_set_string(head, ptr->group->group_name->name); 114 + } else { 115 + tomoyo_set_string(head, ptr->filename->name); 298 116 } 299 - *dp = '\0'; 300 117 } 301 118 302 119 /** 303 - * tomoyo_tokenize - Tokenize string. 120 + * tomoyo_print_number_union - Print a tomoyo_number_union. 304 121 * 305 - * @buffer: The line to tokenize. 306 - * @w: Pointer to "char *". 307 - * @size: Sizeof @w . 308 - * 309 - * Returns true on success, false otherwise. 122 + * @head: Pointer to "struct tomoyo_io_buffer". 123 + * @ptr: Pointer to "struct tomoyo_number_union". 310 124 */ 311 - bool tomoyo_tokenize(char *buffer, char *w[], size_t size) 125 + static void tomoyo_print_number_union(struct tomoyo_io_buffer *head, 126 + const struct tomoyo_number_union *ptr) 312 127 { 313 - int count = size / sizeof(char *); 314 - int i; 315 - for (i = 0; i < count; i++) 316 - w[i] = ""; 317 - for (i = 0; i < count; i++) { 318 - char *cp = strchr(buffer, ' '); 319 - if (cp) 320 - *cp = '\0'; 321 - w[i] = buffer; 322 - if (!cp) 323 - break; 324 - buffer = cp + 1; 325 - } 326 - return i < count || !*buffer; 327 - } 328 - 329 - /** 330 - * tomoyo_is_correct_path - Validate a pathname. 331 - * @filename: The pathname to check. 332 - * @start_type: Should the pathname start with '/'? 333 - * 1 = must / -1 = must not / 0 = don't care 334 - * @pattern_type: Can the pathname contain a wildcard? 335 - * 1 = must / -1 = must not / 0 = don't care 336 - * @end_type: Should the pathname end with '/'? 337 - * 1 = must / -1 = must not / 0 = don't care 338 - * 339 - * Check whether the given filename follows the naming rules. 340 - * Returns true if @filename follows the naming rules, false otherwise. 341 - */ 342 - bool tomoyo_is_correct_path(const char *filename, const s8 start_type, 343 - const s8 pattern_type, const s8 end_type) 344 - { 345 - const char *const start = filename; 346 - bool in_repetition = false; 347 - bool contains_pattern = false; 348 - unsigned char c; 349 - unsigned char d; 350 - unsigned char e; 351 - 352 - if (!filename) 353 - goto out; 354 - c = *filename; 355 - if (start_type == 1) { /* Must start with '/' */ 356 - if (c != '/') 357 - goto out; 358 - } else if (start_type == -1) { /* Must not start with '/' */ 359 - if (c == '/') 360 - goto out; 361 - } 362 - if (c) 363 - c = *(filename + strlen(filename) - 1); 364 - if (end_type == 1) { /* Must end with '/' */ 365 - if (c != '/') 366 - goto out; 367 - } else if (end_type == -1) { /* Must not end with '/' */ 368 - if (c == '/') 369 - goto out; 370 - } 371 - while (1) { 372 - c = *filename++; 373 - if (!c) 374 - break; 375 - if (c == '\\') { 376 - c = *filename++; 377 - switch (c) { 378 - case '\\': /* "\\" */ 379 - continue; 380 - case '$': /* "\$" */ 381 - case '+': /* "\+" */ 382 - case '?': /* "\?" */ 383 - case '*': /* "\*" */ 384 - case '@': /* "\@" */ 385 - case 'x': /* "\x" */ 386 - case 'X': /* "\X" */ 387 - case 'a': /* "\a" */ 388 - case 'A': /* "\A" */ 389 - case '-': /* "\-" */ 390 - if (pattern_type == -1) 391 - break; /* Must not contain pattern */ 392 - contains_pattern = true; 393 - continue; 394 - case '{': /* "/\{" */ 395 - if (filename - 3 < start || 396 - *(filename - 3) != '/') 397 - break; 398 - if (pattern_type == -1) 399 - break; /* Must not contain pattern */ 400 - contains_pattern = true; 401 - in_repetition = true; 402 - continue; 403 - case '}': /* "\}/" */ 404 - if (*filename != '/') 405 - break; 406 - if (!in_repetition) 407 - break; 408 - in_repetition = false; 409 - continue; 410 - case '0': /* "\ooo" */ 411 - case '1': 412 - case '2': 413 - case '3': 414 - d = *filename++; 415 - if (d < '0' || d > '7') 416 - break; 417 - e = *filename++; 418 - if (e < '0' || e > '7') 419 - break; 420 - c = tomoyo_make_byte(c, d, e); 421 - if (tomoyo_is_invalid(c)) 422 - continue; /* pattern is not \000 */ 423 - } 424 - goto out; 425 - } else if (in_repetition && c == '/') { 426 - goto out; 427 - } else if (tomoyo_is_invalid(c)) { 428 - goto out; 429 - } 430 - } 431 - if (pattern_type == 1) { /* Must contain pattern */ 432 - if (!contains_pattern) 433 - goto out; 434 - } 435 - if (in_repetition) 436 - goto out; 437 - return true; 438 - out: 439 - return false; 440 - } 441 - 442 - /** 443 - * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules. 444 - * @domainname: The domainname to check. 445 - * 446 - * Returns true if @domainname follows the naming rules, false otherwise. 447 - */ 448 - bool tomoyo_is_correct_domain(const unsigned char *domainname) 449 - { 450 - unsigned char c; 451 - unsigned char d; 452 - unsigned char e; 453 - 454 - if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME, 455 - TOMOYO_ROOT_NAME_LEN)) 456 - goto out; 457 - domainname += TOMOYO_ROOT_NAME_LEN; 458 - if (!*domainname) 459 - return true; 460 - do { 461 - if (*domainname++ != ' ') 462 - goto out; 463 - if (*domainname++ != '/') 464 - goto out; 465 - while ((c = *domainname) != '\0' && c != ' ') { 466 - domainname++; 467 - if (c == '\\') { 468 - c = *domainname++; 469 - switch ((c)) { 470 - case '\\': /* "\\" */ 471 - continue; 472 - case '0': /* "\ooo" */ 473 - case '1': 474 - case '2': 475 - case '3': 476 - d = *domainname++; 477 - if (d < '0' || d > '7') 478 - break; 479 - e = *domainname++; 480 - if (e < '0' || e > '7') 481 - break; 482 - c = tomoyo_make_byte(c, d, e); 483 - if (tomoyo_is_invalid(c)) 484 - /* pattern is not \000 */ 485 - continue; 486 - } 487 - goto out; 488 - } else if (tomoyo_is_invalid(c)) { 489 - goto out; 490 - } 491 - } 492 - } while (*domainname); 493 - return true; 494 - out: 495 - return false; 496 - } 497 - 498 - /** 499 - * tomoyo_is_domain_def - Check whether the given token can be a domainname. 500 - * 501 - * @buffer: The token to check. 502 - * 503 - * Returns true if @buffer possibly be a domainname, false otherwise. 504 - */ 505 - bool tomoyo_is_domain_def(const unsigned char *buffer) 506 - { 507 - return !strncmp(buffer, TOMOYO_ROOT_NAME, TOMOYO_ROOT_NAME_LEN); 508 - } 509 - 510 - /** 511 - * tomoyo_find_domain - Find a domain by the given name. 512 - * 513 - * @domainname: The domainname to find. 514 - * 515 - * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise. 516 - * 517 - * Caller holds tomoyo_read_lock(). 518 - */ 519 - struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname) 520 - { 521 - struct tomoyo_domain_info *domain; 522 - struct tomoyo_path_info name; 523 - 524 - name.name = domainname; 525 - tomoyo_fill_path_info(&name); 526 - list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { 527 - if (!domain->is_deleted && 528 - !tomoyo_pathcmp(&name, domain->domainname)) 529 - return domain; 530 - } 531 - return NULL; 532 - } 533 - 534 - /** 535 - * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token. 536 - * 537 - * @filename: The string to evaluate. 538 - * 539 - * Returns the initial length without a pattern in @filename. 540 - */ 541 - static int tomoyo_const_part_length(const char *filename) 542 - { 543 - char c; 544 - int len = 0; 545 - 546 - if (!filename) 547 - return 0; 548 - while ((c = *filename++) != '\0') { 549 - if (c != '\\') { 550 - len++; 551 - continue; 552 - } 553 - c = *filename++; 554 - switch (c) { 555 - case '\\': /* "\\" */ 556 - len += 2; 557 - continue; 558 - case '0': /* "\ooo" */ 559 - case '1': 560 - case '2': 561 - case '3': 562 - c = *filename++; 563 - if (c < '0' || c > '7') 128 + tomoyo_set_space(head); 129 + if (ptr->is_group) { 130 + tomoyo_set_string(head, "@"); 131 + tomoyo_set_string(head, ptr->group->group_name->name); 132 + } else { 133 + int i; 134 + unsigned long min = ptr->values[0]; 135 + const unsigned long max = ptr->values[1]; 136 + u8 min_type = ptr->min_type; 137 + const u8 max_type = ptr->max_type; 138 + char buffer[128]; 139 + buffer[0] = '\0'; 140 + for (i = 0; i < 2; i++) { 141 + switch (min_type) { 142 + case TOMOYO_VALUE_TYPE_HEXADECIMAL: 143 + tomoyo_addprintf(buffer, sizeof(buffer), 144 + "0x%lX", min); 564 145 break; 565 - c = *filename++; 566 - if (c < '0' || c > '7') 146 + case TOMOYO_VALUE_TYPE_OCTAL: 147 + tomoyo_addprintf(buffer, sizeof(buffer), 148 + "0%lo", min); 567 149 break; 568 - len += 4; 569 - continue; 570 - } 571 - break; 572 - } 573 - return len; 574 - } 575 - 576 - /** 577 - * tomoyo_fill_path_info - Fill in "struct tomoyo_path_info" members. 578 - * 579 - * @ptr: Pointer to "struct tomoyo_path_info" to fill in. 580 - * 581 - * The caller sets "struct tomoyo_path_info"->name. 582 - */ 583 - void tomoyo_fill_path_info(struct tomoyo_path_info *ptr) 584 - { 585 - const char *name = ptr->name; 586 - const int len = strlen(name); 587 - 588 - ptr->const_len = tomoyo_const_part_length(name); 589 - ptr->is_dir = len && (name[len - 1] == '/'); 590 - ptr->is_patterned = (ptr->const_len < len); 591 - ptr->hash = full_name_hash(name, len); 592 - } 593 - 594 - /** 595 - * tomoyo_file_matches_pattern2 - Pattern matching without '/' character 596 - * and "\-" pattern. 597 - * 598 - * @filename: The start of string to check. 599 - * @filename_end: The end of string to check. 600 - * @pattern: The start of pattern to compare. 601 - * @pattern_end: The end of pattern to compare. 602 - * 603 - * Returns true if @filename matches @pattern, false otherwise. 604 - */ 605 - static bool tomoyo_file_matches_pattern2(const char *filename, 606 - const char *filename_end, 607 - const char *pattern, 608 - const char *pattern_end) 609 - { 610 - while (filename < filename_end && pattern < pattern_end) { 611 - char c; 612 - if (*pattern != '\\') { 613 - if (*filename++ != *pattern++) 614 - return false; 615 - continue; 616 - } 617 - c = *filename; 618 - pattern++; 619 - switch (*pattern) { 620 - int i; 621 - int j; 622 - case '?': 623 - if (c == '/') { 624 - return false; 625 - } else if (c == '\\') { 626 - if (filename[1] == '\\') 627 - filename++; 628 - else if (tomoyo_is_byte_range(filename + 1)) 629 - filename += 3; 630 - else 631 - return false; 632 - } 633 - break; 634 - case '\\': 635 - if (c != '\\') 636 - return false; 637 - if (*++filename != '\\') 638 - return false; 639 - break; 640 - case '+': 641 - if (!isdigit(c)) 642 - return false; 643 - break; 644 - case 'x': 645 - if (!isxdigit(c)) 646 - return false; 647 - break; 648 - case 'a': 649 - if (!tomoyo_is_alphabet_char(c)) 650 - return false; 651 - break; 652 - case '0': 653 - case '1': 654 - case '2': 655 - case '3': 656 - if (c == '\\' && tomoyo_is_byte_range(filename + 1) 657 - && strncmp(filename + 1, pattern, 3) == 0) { 658 - filename += 3; 659 - pattern += 2; 150 + default: 151 + tomoyo_addprintf(buffer, sizeof(buffer), 152 + "%lu", min); 660 153 break; 661 154 } 662 - return false; /* Not matched. */ 663 - case '*': 664 - case '@': 665 - for (i = 0; i <= filename_end - filename; i++) { 666 - if (tomoyo_file_matches_pattern2( 667 - filename + i, filename_end, 668 - pattern + 1, pattern_end)) 669 - return true; 670 - c = filename[i]; 671 - if (c == '.' && *pattern == '@') 672 - break; 673 - if (c != '\\') 674 - continue; 675 - if (filename[i + 1] == '\\') 676 - i++; 677 - else if (tomoyo_is_byte_range(filename + i + 1)) 678 - i += 3; 679 - else 680 - break; /* Bad pattern. */ 681 - } 682 - return false; /* Not matched. */ 683 - default: 684 - j = 0; 685 - c = *pattern; 686 - if (c == '$') { 687 - while (isdigit(filename[j])) 688 - j++; 689 - } else if (c == 'X') { 690 - while (isxdigit(filename[j])) 691 - j++; 692 - } else if (c == 'A') { 693 - while (tomoyo_is_alphabet_char(filename[j])) 694 - j++; 695 - } 696 - for (i = 1; i <= j; i++) { 697 - if (tomoyo_file_matches_pattern2( 698 - filename + i, filename_end, 699 - pattern + 1, pattern_end)) 700 - return true; 701 - } 702 - return false; /* Not matched or bad pattern. */ 155 + if (min == max && min_type == max_type) 156 + break; 157 + tomoyo_addprintf(buffer, sizeof(buffer), "-"); 158 + min_type = max_type; 159 + min = max; 703 160 } 704 - filename++; 705 - pattern++; 161 + tomoyo_io_printf(head, "%s", buffer); 706 162 } 707 - while (*pattern == '\\' && 708 - (*(pattern + 1) == '*' || *(pattern + 1) == '@')) 709 - pattern += 2; 710 - return filename == filename_end && pattern == pattern_end; 711 163 } 712 164 713 165 /** 714 - * tomoyo_file_matches_pattern - Pattern matching without without '/' character. 715 - * 716 - * @filename: The start of string to check. 717 - * @filename_end: The end of string to check. 718 - * @pattern: The start of pattern to compare. 719 - * @pattern_end: The end of pattern to compare. 720 - * 721 - * Returns true if @filename matches @pattern, false otherwise. 722 - */ 723 - static bool tomoyo_file_matches_pattern(const char *filename, 724 - const char *filename_end, 725 - const char *pattern, 726 - const char *pattern_end) 727 - { 728 - const char *pattern_start = pattern; 729 - bool first = true; 730 - bool result; 731 - 732 - while (pattern < pattern_end - 1) { 733 - /* Split at "\-" pattern. */ 734 - if (*pattern++ != '\\' || *pattern++ != '-') 735 - continue; 736 - result = tomoyo_file_matches_pattern2(filename, 737 - filename_end, 738 - pattern_start, 739 - pattern - 2); 740 - if (first) 741 - result = !result; 742 - if (result) 743 - return false; 744 - first = false; 745 - pattern_start = pattern; 746 - } 747 - result = tomoyo_file_matches_pattern2(filename, filename_end, 748 - pattern_start, pattern_end); 749 - return first ? result : !result; 750 - } 751 - 752 - /** 753 - * tomoyo_path_matches_pattern2 - Do pathname pattern matching. 754 - * 755 - * @f: The start of string to check. 756 - * @p: The start of pattern to compare. 757 - * 758 - * Returns true if @f matches @p, false otherwise. 759 - */ 760 - static bool tomoyo_path_matches_pattern2(const char *f, const char *p) 761 - { 762 - const char *f_delimiter; 763 - const char *p_delimiter; 764 - 765 - while (*f && *p) { 766 - f_delimiter = strchr(f, '/'); 767 - if (!f_delimiter) 768 - f_delimiter = f + strlen(f); 769 - p_delimiter = strchr(p, '/'); 770 - if (!p_delimiter) 771 - p_delimiter = p + strlen(p); 772 - if (*p == '\\' && *(p + 1) == '{') 773 - goto recursive; 774 - if (!tomoyo_file_matches_pattern(f, f_delimiter, p, 775 - p_delimiter)) 776 - return false; 777 - f = f_delimiter; 778 - if (*f) 779 - f++; 780 - p = p_delimiter; 781 - if (*p) 782 - p++; 783 - } 784 - /* Ignore trailing "\*" and "\@" in @pattern. */ 785 - while (*p == '\\' && 786 - (*(p + 1) == '*' || *(p + 1) == '@')) 787 - p += 2; 788 - return !*f && !*p; 789 - recursive: 790 - /* 791 - * The "\{" pattern is permitted only after '/' character. 792 - * This guarantees that below "*(p - 1)" is safe. 793 - * Also, the "\}" pattern is permitted only before '/' character 794 - * so that "\{" + "\}" pair will not break the "\-" operator. 795 - */ 796 - if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' || 797 - *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\') 798 - return false; /* Bad pattern. */ 799 - do { 800 - /* Compare current component with pattern. */ 801 - if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2, 802 - p_delimiter - 2)) 803 - break; 804 - /* Proceed to next component. */ 805 - f = f_delimiter; 806 - if (!*f) 807 - break; 808 - f++; 809 - /* Continue comparison. */ 810 - if (tomoyo_path_matches_pattern2(f, p_delimiter + 1)) 811 - return true; 812 - f_delimiter = strchr(f, '/'); 813 - } while (f_delimiter); 814 - return false; /* Not matched. */ 815 - } 816 - 817 - /** 818 - * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern. 819 - * 820 - * @filename: The filename to check. 821 - * @pattern: The pattern to compare. 822 - * 823 - * Returns true if matches, false otherwise. 824 - * 825 - * The following patterns are available. 826 - * \\ \ itself. 827 - * \ooo Octal representation of a byte. 828 - * \* Zero or more repetitions of characters other than '/'. 829 - * \@ Zero or more repetitions of characters other than '/' or '.'. 830 - * \? 1 byte character other than '/'. 831 - * \$ One or more repetitions of decimal digits. 832 - * \+ 1 decimal digit. 833 - * \X One or more repetitions of hexadecimal digits. 834 - * \x 1 hexadecimal digit. 835 - * \A One or more repetitions of alphabet characters. 836 - * \a 1 alphabet character. 837 - * 838 - * \- Subtraction operator. 839 - * 840 - * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/ 841 - * /dir/dir/dir/ ). 842 - */ 843 - bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, 844 - const struct tomoyo_path_info *pattern) 845 - { 846 - const char *f = filename->name; 847 - const char *p = pattern->name; 848 - const int len = pattern->const_len; 849 - 850 - /* If @pattern doesn't contain pattern, I can use strcmp(). */ 851 - if (!pattern->is_patterned) 852 - return !tomoyo_pathcmp(filename, pattern); 853 - /* Don't compare directory and non-directory. */ 854 - if (filename->is_dir != pattern->is_dir) 855 - return false; 856 - /* Compare the initial length without patterns. */ 857 - if (strncmp(f, p, len)) 858 - return false; 859 - f += len; 860 - p += len; 861 - return tomoyo_path_matches_pattern2(f, p); 862 - } 863 - 864 - /** 865 - * tomoyo_io_printf - Transactional printf() to "struct tomoyo_io_buffer" structure. 866 - * 867 - * @head: Pointer to "struct tomoyo_io_buffer". 868 - * @fmt: The printf()'s format string, followed by parameters. 869 - * 870 - * Returns true if output was written, false otherwise. 871 - * 872 - * The snprintf() will truncate, but tomoyo_io_printf() won't. 873 - */ 874 - bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) 875 - { 876 - va_list args; 877 - int len; 878 - int pos = head->read_avail; 879 - int size = head->readbuf_size - pos; 880 - 881 - if (size <= 0) 882 - return false; 883 - va_start(args, fmt); 884 - len = vsnprintf(head->read_buf + pos, size, fmt, args); 885 - va_end(args); 886 - if (pos + len >= head->readbuf_size) 887 - return false; 888 - head->read_avail += len; 889 - return true; 890 - } 891 - 892 - /** 893 - * tomoyo_get_exe - Get tomoyo_realpath() of current process. 894 - * 895 - * Returns the tomoyo_realpath() of current process on success, NULL otherwise. 896 - * 897 - * This function uses kzalloc(), so the caller must call kfree() 898 - * if this function didn't return NULL. 899 - */ 900 - static const char *tomoyo_get_exe(void) 901 - { 902 - struct mm_struct *mm = current->mm; 903 - struct vm_area_struct *vma; 904 - const char *cp = NULL; 905 - 906 - if (!mm) 907 - return NULL; 908 - down_read(&mm->mmap_sem); 909 - for (vma = mm->mmap; vma; vma = vma->vm_next) { 910 - if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) { 911 - cp = tomoyo_realpath_from_path(&vma->vm_file->f_path); 912 - break; 913 - } 914 - } 915 - up_read(&mm->mmap_sem); 916 - return cp; 917 - } 918 - 919 - /** 920 - * tomoyo_get_msg - Get warning message. 921 - * 922 - * @is_enforce: Is it enforcing mode? 923 - * 924 - * Returns "ERROR" or "WARNING". 925 - */ 926 - const char *tomoyo_get_msg(const bool is_enforce) 927 - { 928 - if (is_enforce) 929 - return "ERROR"; 930 - else 931 - return "WARNING"; 932 - } 933 - 934 - /** 935 - * tomoyo_check_flags - Check mode for specified functionality. 936 - * 937 - * @domain: Pointer to "struct tomoyo_domain_info". 938 - * @index: The functionality to check mode. 939 - * 940 - * TOMOYO checks only process context. 941 - * This code disables TOMOYO's enforcement in case the function is called from 942 - * interrupt context. 943 - */ 944 - unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, 945 - const u8 index) 946 - { 947 - const u8 profile = domain->profile; 948 - 949 - if (WARN_ON(in_interrupt())) 950 - return 0; 951 - return tomoyo_policy_loaded && index < TOMOYO_MAX_CONTROL_INDEX 952 - #if TOMOYO_MAX_PROFILES != 256 953 - && profile < TOMOYO_MAX_PROFILES 954 - #endif 955 - && tomoyo_profile_ptr[profile] ? 956 - tomoyo_profile_ptr[profile]->value[index] : 0; 957 - } 958 - 959 - /** 960 - * tomoyo_verbose_mode - Check whether TOMOYO is verbose mode. 961 - * 962 - * @domain: Pointer to "struct tomoyo_domain_info". 963 - * 964 - * Returns true if domain policy violation warning should be printed to 965 - * console. 966 - */ 967 - bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain) 968 - { 969 - return tomoyo_check_flags(domain, TOMOYO_VERBOSE) != 0; 970 - } 971 - 972 - /** 973 - * tomoyo_domain_quota_is_ok - Check for domain's quota. 974 - * 975 - * @domain: Pointer to "struct tomoyo_domain_info". 976 - * 977 - * Returns true if the domain is not exceeded quota, false otherwise. 978 - * 979 - * Caller holds tomoyo_read_lock(). 980 - */ 981 - bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) 982 - { 983 - unsigned int count = 0; 984 - struct tomoyo_acl_info *ptr; 985 - 986 - if (!domain) 987 - return true; 988 - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 989 - switch (ptr->type) { 990 - struct tomoyo_path_acl *acl; 991 - u32 perm; 992 - u8 i; 993 - case TOMOYO_TYPE_PATH_ACL: 994 - acl = container_of(ptr, struct tomoyo_path_acl, head); 995 - perm = acl->perm | (((u32) acl->perm_high) << 16); 996 - for (i = 0; i < TOMOYO_MAX_PATH_OPERATION; i++) 997 - if (perm & (1 << i)) 998 - count++; 999 - if (perm & (1 << TOMOYO_TYPE_READ_WRITE)) 1000 - count -= 2; 1001 - break; 1002 - case TOMOYO_TYPE_PATH2_ACL: 1003 - perm = container_of(ptr, struct tomoyo_path2_acl, head) 1004 - ->perm; 1005 - for (i = 0; i < TOMOYO_MAX_PATH2_OPERATION; i++) 1006 - if (perm & (1 << i)) 1007 - count++; 1008 - break; 1009 - } 1010 - } 1011 - if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY)) 1012 - return true; 1013 - if (!domain->quota_warned) { 1014 - domain->quota_warned = true; 1015 - printk(KERN_WARNING "TOMOYO-WARNING: " 1016 - "Domain '%s' has so many ACLs to hold. " 1017 - "Stopped learning mode.\n", domain->domainname->name); 1018 - } 1019 - return false; 1020 - } 1021 - 1022 - /** 1023 - * tomoyo_find_or_assign_new_profile - Create a new profile. 166 + * tomoyo_assign_profile - Create a new profile. 1024 167 * 1025 168 * @profile: Profile number to create. 1026 169 * 1027 170 * Returns pointer to "struct tomoyo_profile" on success, NULL otherwise. 1028 171 */ 1029 - static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned 1030 - int profile) 172 + static struct tomoyo_profile *tomoyo_assign_profile(const unsigned int profile) 1031 173 { 1032 - struct tomoyo_profile *ptr = NULL; 1033 - int i; 1034 - 174 + struct tomoyo_profile *ptr; 175 + struct tomoyo_profile *entry; 1035 176 if (profile >= TOMOYO_MAX_PROFILES) 1036 - return NULL; 1037 - if (mutex_lock_interruptible(&tomoyo_policy_lock)) 1038 177 return NULL; 1039 178 ptr = tomoyo_profile_ptr[profile]; 1040 179 if (ptr) 1041 - goto ok; 1042 - ptr = kmalloc(sizeof(*ptr), GFP_NOFS); 1043 - if (!tomoyo_memory_ok(ptr)) { 1044 - kfree(ptr); 1045 - ptr = NULL; 1046 - goto ok; 180 + return ptr; 181 + entry = kzalloc(sizeof(*entry), GFP_NOFS); 182 + if (mutex_lock_interruptible(&tomoyo_policy_lock)) 183 + goto out; 184 + ptr = tomoyo_profile_ptr[profile]; 185 + if (!ptr && tomoyo_memory_ok(entry)) { 186 + ptr = entry; 187 + ptr->learning = &tomoyo_default_profile.preference; 188 + ptr->permissive = &tomoyo_default_profile.preference; 189 + ptr->enforcing = &tomoyo_default_profile.preference; 190 + ptr->default_config = TOMOYO_CONFIG_DISABLED; 191 + memset(ptr->config, TOMOYO_CONFIG_USE_DEFAULT, 192 + sizeof(ptr->config)); 193 + mb(); /* Avoid out-of-order execution. */ 194 + tomoyo_profile_ptr[profile] = ptr; 195 + entry = NULL; 1047 196 } 1048 - for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) 1049 - ptr->value[i] = tomoyo_control_array[i].current_value; 1050 - mb(); /* Avoid out-of-order execution. */ 1051 - tomoyo_profile_ptr[profile] = ptr; 1052 - ok: 1053 197 mutex_unlock(&tomoyo_policy_lock); 198 + out: 199 + kfree(entry); 1054 200 return ptr; 1055 201 } 1056 202 1057 203 /** 1058 - * tomoyo_write_profile - Write to profile table. 204 + * tomoyo_profile - Find a profile. 205 + * 206 + * @profile: Profile number to find. 207 + * 208 + * Returns pointer to "struct tomoyo_profile". 209 + */ 210 + struct tomoyo_profile *tomoyo_profile(const u8 profile) 211 + { 212 + struct tomoyo_profile *ptr = tomoyo_profile_ptr[profile]; 213 + if (!tomoyo_policy_loaded) 214 + return &tomoyo_default_profile; 215 + BUG_ON(!ptr); 216 + return ptr; 217 + } 218 + 219 + static s8 tomoyo_find_yesno(const char *string, const char *find) 220 + { 221 + const char *cp = strstr(string, find); 222 + if (cp) { 223 + cp += strlen(find); 224 + if (!strncmp(cp, "=yes", 4)) 225 + return 1; 226 + else if (!strncmp(cp, "=no", 3)) 227 + return 0; 228 + } 229 + return -1; 230 + } 231 + 232 + static void tomoyo_set_bool(bool *b, const char *string, const char *find) 233 + { 234 + switch (tomoyo_find_yesno(string, find)) { 235 + case 1: 236 + *b = true; 237 + break; 238 + case 0: 239 + *b = false; 240 + break; 241 + } 242 + } 243 + 244 + static void tomoyo_set_uint(unsigned int *i, const char *string, 245 + const char *find) 246 + { 247 + const char *cp = strstr(string, find); 248 + if (cp) 249 + sscanf(cp + strlen(find), "=%u", i); 250 + } 251 + 252 + static void tomoyo_set_pref(const char *name, const char *value, 253 + const bool use_default, 254 + struct tomoyo_profile *profile) 255 + { 256 + struct tomoyo_preference **pref; 257 + bool *verbose; 258 + if (!strcmp(name, "enforcing")) { 259 + if (use_default) { 260 + pref = &profile->enforcing; 261 + goto set_default; 262 + } 263 + profile->enforcing = &profile->preference; 264 + verbose = &profile->preference.enforcing_verbose; 265 + goto set_verbose; 266 + } 267 + if (!strcmp(name, "permissive")) { 268 + if (use_default) { 269 + pref = &profile->permissive; 270 + goto set_default; 271 + } 272 + profile->permissive = &profile->preference; 273 + verbose = &profile->preference.permissive_verbose; 274 + goto set_verbose; 275 + } 276 + if (!strcmp(name, "learning")) { 277 + if (use_default) { 278 + pref = &profile->learning; 279 + goto set_default; 280 + } 281 + profile->learning = &profile->preference; 282 + tomoyo_set_uint(&profile->preference.learning_max_entry, value, 283 + "max_entry"); 284 + verbose = &profile->preference.learning_verbose; 285 + goto set_verbose; 286 + } 287 + return; 288 + set_default: 289 + *pref = &tomoyo_default_profile.preference; 290 + return; 291 + set_verbose: 292 + tomoyo_set_bool(verbose, value, "verbose"); 293 + } 294 + 295 + static int tomoyo_set_mode(char *name, const char *value, 296 + const bool use_default, 297 + struct tomoyo_profile *profile) 298 + { 299 + u8 i; 300 + u8 config; 301 + if (!strcmp(name, "CONFIG")) { 302 + i = TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX; 303 + config = profile->default_config; 304 + } else if (tomoyo_str_starts(&name, "CONFIG::")) { 305 + config = 0; 306 + for (i = 0; i < TOMOYO_MAX_MAC_INDEX 307 + + TOMOYO_MAX_MAC_CATEGORY_INDEX; i++) { 308 + if (strcmp(name, tomoyo_mac_keywords[i])) 309 + continue; 310 + config = profile->config[i]; 311 + break; 312 + } 313 + if (i == TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX) 314 + return -EINVAL; 315 + } else { 316 + return -EINVAL; 317 + } 318 + if (use_default) { 319 + config = TOMOYO_CONFIG_USE_DEFAULT; 320 + } else { 321 + u8 mode; 322 + for (mode = 0; mode < 4; mode++) 323 + if (strstr(value, tomoyo_mode[mode])) 324 + /* 325 + * Update lower 3 bits in order to distinguish 326 + * 'config' from 'TOMOYO_CONFIG_USE_DEAFULT'. 327 + */ 328 + config = (config & ~7) | mode; 329 + } 330 + if (i < TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX) 331 + profile->config[i] = config; 332 + else if (config != TOMOYO_CONFIG_USE_DEFAULT) 333 + profile->default_config = config; 334 + return 0; 335 + } 336 + 337 + /** 338 + * tomoyo_write_profile - Write profile table. 1059 339 * 1060 340 * @head: Pointer to "struct tomoyo_io_buffer". 1061 341 * ··· 430 980 { 431 981 char *data = head->write_buf; 432 982 unsigned int i; 433 - unsigned int value; 983 + bool use_default = false; 434 984 char *cp; 435 985 struct tomoyo_profile *profile; 436 - unsigned long num; 437 - 438 - cp = strchr(data, '-'); 439 - if (cp) 440 - *cp = '\0'; 441 - if (strict_strtoul(data, 10, &num)) 442 - return -EINVAL; 443 - if (cp) 986 + if (sscanf(data, "PROFILE_VERSION=%u", &tomoyo_profile_version) == 1) 987 + return 0; 988 + i = simple_strtoul(data, &cp, 10); 989 + if (data == cp) { 990 + profile = &tomoyo_default_profile; 991 + } else { 992 + if (*cp != '-') 993 + return -EINVAL; 444 994 data = cp + 1; 445 - profile = tomoyo_find_or_assign_new_profile(num); 446 - if (!profile) 447 - return -EINVAL; 995 + profile = tomoyo_assign_profile(i); 996 + if (!profile) 997 + return -EINVAL; 998 + } 448 999 cp = strchr(data, '='); 449 1000 if (!cp) 450 1001 return -EINVAL; 451 - *cp = '\0'; 1002 + *cp++ = '\0'; 1003 + if (profile != &tomoyo_default_profile) 1004 + use_default = strstr(cp, "use_default") != NULL; 1005 + if (tomoyo_str_starts(&data, "PREFERENCE::")) { 1006 + tomoyo_set_pref(data, cp, use_default, profile); 1007 + return 0; 1008 + } 1009 + if (profile == &tomoyo_default_profile) 1010 + return -EINVAL; 452 1011 if (!strcmp(data, "COMMENT")) { 453 1012 const struct tomoyo_path_info *old_comment = profile->comment; 454 - profile->comment = tomoyo_get_name(cp + 1); 1013 + profile->comment = tomoyo_get_name(cp); 455 1014 tomoyo_put_name(old_comment); 456 1015 return 0; 457 1016 } 458 - for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) { 459 - if (strcmp(data, tomoyo_control_array[i].keyword)) 460 - continue; 461 - if (sscanf(cp + 1, "%u", &value) != 1) { 462 - int j; 463 - const char **modes; 464 - switch (i) { 465 - case TOMOYO_VERBOSE: 466 - modes = tomoyo_mode_2; 467 - break; 468 - default: 469 - modes = tomoyo_mode_4; 470 - break; 471 - } 472 - for (j = 0; j < 4; j++) { 473 - if (strcmp(cp + 1, modes[j])) 474 - continue; 475 - value = j; 476 - break; 477 - } 478 - if (j == 4) 479 - return -EINVAL; 480 - } else if (value > tomoyo_control_array[i].max_value) { 481 - value = tomoyo_control_array[i].max_value; 482 - } 483 - profile->value[i] = value; 484 - return 0; 1017 + return tomoyo_set_mode(data, cp, use_default, profile); 1018 + } 1019 + 1020 + static void tomoyo_print_preference(struct tomoyo_io_buffer *head, 1021 + const int idx) 1022 + { 1023 + struct tomoyo_preference *pref = &tomoyo_default_profile.preference; 1024 + const struct tomoyo_profile *profile = idx >= 0 ? 1025 + tomoyo_profile_ptr[idx] : NULL; 1026 + char buffer[16] = ""; 1027 + if (profile) { 1028 + buffer[sizeof(buffer) - 1] = '\0'; 1029 + snprintf(buffer, sizeof(buffer) - 1, "%u-", idx); 485 1030 } 486 - return -EINVAL; 1031 + if (profile) { 1032 + pref = profile->learning; 1033 + if (pref == &tomoyo_default_profile.preference) 1034 + goto skip1; 1035 + } 1036 + tomoyo_io_printf(head, "%sPREFERENCE::%s={ " 1037 + "verbose=%s max_entry=%u }\n", 1038 + buffer, "learning", 1039 + tomoyo_yesno(pref->learning_verbose), 1040 + pref->learning_max_entry); 1041 + skip1: 1042 + if (profile) { 1043 + pref = profile->permissive; 1044 + if (pref == &tomoyo_default_profile.preference) 1045 + goto skip2; 1046 + } 1047 + tomoyo_io_printf(head, "%sPREFERENCE::%s={ verbose=%s }\n", 1048 + buffer, "permissive", 1049 + tomoyo_yesno(pref->permissive_verbose)); 1050 + skip2: 1051 + if (profile) { 1052 + pref = profile->enforcing; 1053 + if (pref == &tomoyo_default_profile.preference) 1054 + return; 1055 + } 1056 + tomoyo_io_printf(head, "%sPREFERENCE::%s={ verbose=%s }\n", 1057 + buffer, "enforcing", 1058 + tomoyo_yesno(pref->enforcing_verbose)); 1059 + } 1060 + 1061 + static void tomoyo_print_config(struct tomoyo_io_buffer *head, const u8 config) 1062 + { 1063 + tomoyo_io_printf(head, "={ mode=%s }\n", tomoyo_mode[config & 3]); 487 1064 } 488 1065 489 1066 /** 490 - * tomoyo_read_profile - Read from profile table. 1067 + * tomoyo_read_profile - Read profile table. 491 1068 * 492 1069 * @head: Pointer to "struct tomoyo_io_buffer". 493 - * 494 - * Returns 0. 495 1070 */ 496 - static int tomoyo_read_profile(struct tomoyo_io_buffer *head) 1071 + static void tomoyo_read_profile(struct tomoyo_io_buffer *head) 497 1072 { 498 - static const int total = TOMOYO_MAX_CONTROL_INDEX + 1; 499 - int step; 500 - 501 - if (head->read_eof) 502 - return 0; 503 - for (step = head->read_step; step < TOMOYO_MAX_PROFILES * total; 504 - step++) { 505 - const u8 index = step / total; 506 - u8 type = step % total; 507 - const struct tomoyo_profile *profile 508 - = tomoyo_profile_ptr[index]; 509 - head->read_step = step; 510 - if (!profile) 511 - continue; 512 - if (!type) { /* Print profile' comment tag. */ 513 - if (!tomoyo_io_printf(head, "%u-COMMENT=%s\n", 514 - index, profile->comment ? 515 - profile->comment->name : "")) 1073 + u8 index; 1074 + const struct tomoyo_profile *profile; 1075 + next: 1076 + index = head->r.index; 1077 + profile = tomoyo_profile_ptr[index]; 1078 + switch (head->r.step) { 1079 + case 0: 1080 + tomoyo_io_printf(head, "PROFILE_VERSION=%s\n", "20090903"); 1081 + tomoyo_print_preference(head, -1); 1082 + head->r.step++; 1083 + break; 1084 + case 1: 1085 + for ( ; head->r.index < TOMOYO_MAX_PROFILES; 1086 + head->r.index++) 1087 + if (tomoyo_profile_ptr[head->r.index]) 516 1088 break; 517 - continue; 1089 + if (head->r.index == TOMOYO_MAX_PROFILES) 1090 + return; 1091 + head->r.step++; 1092 + break; 1093 + case 2: 1094 + { 1095 + const struct tomoyo_path_info *comment = 1096 + profile->comment; 1097 + tomoyo_io_printf(head, "%u-COMMENT=", index); 1098 + tomoyo_set_string(head, comment ? comment->name : ""); 1099 + tomoyo_set_lf(head); 1100 + head->r.step++; 518 1101 } 519 - type--; 520 - if (type < TOMOYO_MAX_CONTROL_INDEX) { 521 - const unsigned int value = profile->value[type]; 522 - const char **modes = NULL; 523 - const char *keyword 524 - = tomoyo_control_array[type].keyword; 525 - switch (tomoyo_control_array[type].max_value) { 526 - case 3: 527 - modes = tomoyo_mode_4; 528 - break; 529 - case 1: 530 - modes = tomoyo_mode_2; 531 - break; 532 - } 533 - if (modes) { 534 - if (!tomoyo_io_printf(head, "%u-%s=%s\n", index, 535 - keyword, modes[value])) 536 - break; 537 - } else { 538 - if (!tomoyo_io_printf(head, "%u-%s=%u\n", index, 539 - keyword, value)) 540 - break; 541 - } 1102 + break; 1103 + case 3: 1104 + { 1105 + tomoyo_io_printf(head, "%u-%s", index, "CONFIG"); 1106 + tomoyo_print_config(head, profile->default_config); 1107 + head->r.bit = 0; 1108 + head->r.step++; 542 1109 } 1110 + break; 1111 + case 4: 1112 + for ( ; head->r.bit < TOMOYO_MAX_MAC_INDEX 1113 + + TOMOYO_MAX_MAC_CATEGORY_INDEX; head->r.bit++) { 1114 + const u8 i = head->r.bit; 1115 + const u8 config = profile->config[i]; 1116 + if (config == TOMOYO_CONFIG_USE_DEFAULT) 1117 + continue; 1118 + tomoyo_io_printf(head, "%u-%s%s", index, "CONFIG::", 1119 + tomoyo_mac_keywords[i]); 1120 + tomoyo_print_config(head, config); 1121 + head->r.bit++; 1122 + break; 1123 + } 1124 + if (head->r.bit == TOMOYO_MAX_MAC_INDEX 1125 + + TOMOYO_MAX_MAC_CATEGORY_INDEX) { 1126 + tomoyo_print_preference(head, index); 1127 + head->r.index++; 1128 + head->r.step = 1; 1129 + } 1130 + break; 543 1131 } 544 - if (step == TOMOYO_MAX_PROFILES * total) 545 - head->read_eof = true; 546 - return 0; 1132 + if (tomoyo_flush(head)) 1133 + goto next; 547 1134 } 548 1135 549 - /* 550 - * tomoyo_policy_manager_list is used for holding list of domainnames or 551 - * programs which are permitted to modify configuration via 552 - * /sys/kernel/security/tomoyo/ interface. 553 - * 554 - * An entry is added by 555 - * 556 - * # echo '<kernel> /sbin/mingetty /bin/login /bin/bash' > \ 557 - * /sys/kernel/security/tomoyo/manager 558 - * (if you want to specify by a domainname) 559 - * 560 - * or 561 - * 562 - * # echo '/usr/lib/ccs/editpolicy' > /sys/kernel/security/tomoyo/manager 563 - * (if you want to specify by a program's location) 564 - * 565 - * and is deleted by 566 - * 567 - * # echo 'delete <kernel> /sbin/mingetty /bin/login /bin/bash' > \ 568 - * /sys/kernel/security/tomoyo/manager 569 - * 570 - * or 571 - * 572 - * # echo 'delete /usr/lib/ccs/editpolicy' > \ 573 - * /sys/kernel/security/tomoyo/manager 574 - * 575 - * and all entries are retrieved by 576 - * 577 - * # cat /sys/kernel/security/tomoyo/manager 578 - */ 579 - LIST_HEAD(tomoyo_policy_manager_list); 1136 + static bool tomoyo_same_manager(const struct tomoyo_acl_head *a, 1137 + const struct tomoyo_acl_head *b) 1138 + { 1139 + return container_of(a, struct tomoyo_manager, head)->manager == 1140 + container_of(b, struct tomoyo_manager, head)->manager; 1141 + } 580 1142 581 1143 /** 582 1144 * tomoyo_update_manager_entry - Add a manager entry. ··· 603 1141 static int tomoyo_update_manager_entry(const char *manager, 604 1142 const bool is_delete) 605 1143 { 606 - struct tomoyo_policy_manager_entry *ptr; 607 - struct tomoyo_policy_manager_entry e = { }; 608 - int error = is_delete ? -ENOENT : -ENOMEM; 1144 + struct tomoyo_manager e = { }; 1145 + int error; 609 1146 610 - if (tomoyo_is_domain_def(manager)) { 611 - if (!tomoyo_is_correct_domain(manager)) 1147 + if (tomoyo_domain_def(manager)) { 1148 + if (!tomoyo_correct_domain(manager)) 612 1149 return -EINVAL; 613 1150 e.is_domain = true; 614 1151 } else { 615 - if (!tomoyo_is_correct_path(manager, 1, -1, -1)) 1152 + if (!tomoyo_correct_path(manager)) 616 1153 return -EINVAL; 617 1154 } 618 1155 e.manager = tomoyo_get_name(manager); 619 1156 if (!e.manager) 620 1157 return -ENOMEM; 621 - if (mutex_lock_interruptible(&tomoyo_policy_lock)) 622 - goto out; 623 - list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { 624 - if (ptr->manager != e.manager) 625 - continue; 626 - ptr->is_deleted = is_delete; 627 - error = 0; 628 - break; 629 - } 630 - if (!is_delete && error) { 631 - struct tomoyo_policy_manager_entry *entry = 632 - tomoyo_commit_ok(&e, sizeof(e)); 633 - if (entry) { 634 - list_add_tail_rcu(&entry->list, 635 - &tomoyo_policy_manager_list); 636 - error = 0; 637 - } 638 - } 639 - mutex_unlock(&tomoyo_policy_lock); 640 - out: 1158 + error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 1159 + &tomoyo_policy_list[TOMOYO_ID_MANAGER], 1160 + tomoyo_same_manager); 641 1161 tomoyo_put_name(e.manager); 642 1162 return error; 643 1163 } 644 1164 645 1165 /** 646 - * tomoyo_write_manager_policy - Write manager policy. 1166 + * tomoyo_write_manager - Write manager policy. 647 1167 * 648 1168 * @head: Pointer to "struct tomoyo_io_buffer". 649 1169 * ··· 633 1189 * 634 1190 * Caller holds tomoyo_read_lock(). 635 1191 */ 636 - static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head) 1192 + static int tomoyo_write_manager(struct tomoyo_io_buffer *head) 637 1193 { 638 1194 char *data = head->write_buf; 639 1195 bool is_delete = tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE); ··· 646 1202 } 647 1203 648 1204 /** 649 - * tomoyo_read_manager_policy - Read manager policy. 1205 + * tomoyo_read_manager - Read manager policy. 650 1206 * 651 1207 * @head: Pointer to "struct tomoyo_io_buffer". 652 1208 * 653 - * Returns 0. 654 - * 655 1209 * Caller holds tomoyo_read_lock(). 656 1210 */ 657 - static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) 1211 + static void tomoyo_read_manager(struct tomoyo_io_buffer *head) 658 1212 { 659 - struct list_head *pos; 660 - bool done = true; 661 - 662 - if (head->read_eof) 663 - return 0; 664 - list_for_each_cookie(pos, head->read_var2, 665 - &tomoyo_policy_manager_list) { 666 - struct tomoyo_policy_manager_entry *ptr; 667 - ptr = list_entry(pos, struct tomoyo_policy_manager_entry, 668 - list); 669 - if (ptr->is_deleted) 1213 + if (head->r.eof) 1214 + return; 1215 + list_for_each_cookie(head->r.acl, 1216 + &tomoyo_policy_list[TOMOYO_ID_MANAGER]) { 1217 + struct tomoyo_manager *ptr = 1218 + list_entry(head->r.acl, typeof(*ptr), head.list); 1219 + if (ptr->head.is_deleted) 670 1220 continue; 671 - done = tomoyo_io_printf(head, "%s\n", ptr->manager->name); 672 - if (!done) 673 - break; 1221 + if (!tomoyo_flush(head)) 1222 + return; 1223 + tomoyo_set_string(head, ptr->manager->name); 1224 + tomoyo_set_lf(head); 674 1225 } 675 - head->read_eof = done; 676 - return 0; 1226 + head->r.eof = true; 677 1227 } 678 1228 679 1229 /** 680 - * tomoyo_is_policy_manager - Check whether the current process is a policy manager. 1230 + * tomoyo_manager - Check whether the current process is a policy manager. 681 1231 * 682 1232 * Returns true if the current process is permitted to modify policy 683 1233 * via /sys/kernel/security/tomoyo/ interface. 684 1234 * 685 1235 * Caller holds tomoyo_read_lock(). 686 1236 */ 687 - static bool tomoyo_is_policy_manager(void) 1237 + static bool tomoyo_manager(void) 688 1238 { 689 - struct tomoyo_policy_manager_entry *ptr; 1239 + struct tomoyo_manager *ptr; 690 1240 const char *exe; 691 1241 const struct task_struct *task = current; 692 1242 const struct tomoyo_path_info *domainname = tomoyo_domain()->domainname; ··· 690 1252 return true; 691 1253 if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid)) 692 1254 return false; 693 - list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { 694 - if (!ptr->is_deleted && ptr->is_domain 1255 + list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_MANAGER], 1256 + head.list) { 1257 + if (!ptr->head.is_deleted && ptr->is_domain 695 1258 && !tomoyo_pathcmp(domainname, ptr->manager)) { 696 1259 found = true; 697 1260 break; ··· 703 1264 exe = tomoyo_get_exe(); 704 1265 if (!exe) 705 1266 return false; 706 - list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { 707 - if (!ptr->is_deleted && !ptr->is_domain 1267 + list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_MANAGER], 1268 + head.list) { 1269 + if (!ptr->head.is_deleted && !ptr->is_domain 708 1270 && !strcmp(exe, ptr->manager->name)) { 709 1271 found = true; 710 1272 break; ··· 725 1285 } 726 1286 727 1287 /** 728 - * tomoyo_is_select_one - Parse select command. 1288 + * tomoyo_select_one - Parse select command. 729 1289 * 730 1290 * @head: Pointer to "struct tomoyo_io_buffer". 731 1291 * @data: String to parse. ··· 734 1294 * 735 1295 * Caller holds tomoyo_read_lock(). 736 1296 */ 737 - static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, 738 - const char *data) 1297 + static bool tomoyo_select_one(struct tomoyo_io_buffer *head, const char *data) 739 1298 { 740 1299 unsigned int pid; 741 1300 struct tomoyo_domain_info *domain = NULL; 1301 + bool global_pid = false; 742 1302 743 - if (sscanf(data, "pid=%u", &pid) == 1) { 1303 + if (!strcmp(data, "allow_execute")) { 1304 + head->r.print_execute_only = true; 1305 + return true; 1306 + } 1307 + if (sscanf(data, "pid=%u", &pid) == 1 || 1308 + (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) { 744 1309 struct task_struct *p; 745 1310 rcu_read_lock(); 746 1311 read_lock(&tasklist_lock); 747 - p = find_task_by_vpid(pid); 1312 + if (global_pid) 1313 + p = find_task_by_pid_ns(pid, &init_pid_ns); 1314 + else 1315 + p = find_task_by_vpid(pid); 748 1316 if (p) 749 1317 domain = tomoyo_real_domain(p); 750 1318 read_unlock(&tasklist_lock); 751 1319 rcu_read_unlock(); 752 1320 } else if (!strncmp(data, "domain=", 7)) { 753 - if (tomoyo_is_domain_def(data + 7)) 1321 + if (tomoyo_domain_def(data + 7)) 754 1322 domain = tomoyo_find_domain(data + 7); 755 1323 } else 756 1324 return false; ··· 766 1318 /* Accessing read_buf is safe because head->io_sem is held. */ 767 1319 if (!head->read_buf) 768 1320 return true; /* Do nothing if open(O_WRONLY). */ 769 - head->read_avail = 0; 1321 + memset(&head->r, 0, sizeof(head->r)); 1322 + head->r.print_this_domain_only = true; 1323 + head->r.eof = !domain; 1324 + head->r.domain = &domain->list; 770 1325 tomoyo_io_printf(head, "# select %s\n", data); 771 - head->read_single_domain = true; 772 - head->read_eof = !domain; 773 - if (domain) { 774 - struct tomoyo_domain_info *d; 775 - head->read_var1 = NULL; 776 - list_for_each_entry_rcu(d, &tomoyo_domain_list, list) { 777 - if (d == domain) 778 - break; 779 - head->read_var1 = &d->list; 780 - } 781 - head->read_var2 = NULL; 782 - head->read_bit = 0; 783 - head->read_step = 0; 784 - if (domain->is_deleted) 785 - tomoyo_io_printf(head, "# This is a deleted domain.\n"); 786 - } 1326 + if (domain && domain->is_deleted) 1327 + tomoyo_io_printf(head, "# This is a deleted domain.\n"); 787 1328 return true; 788 1329 } 789 1330 ··· 810 1373 } 811 1374 812 1375 /** 813 - * tomoyo_write_domain_policy - Write domain policy. 1376 + * tomoyo_write_domain2 - Write domain policy. 814 1377 * 815 1378 * @head: Pointer to "struct tomoyo_io_buffer". 816 1379 * ··· 818 1381 * 819 1382 * Caller holds tomoyo_read_lock(). 820 1383 */ 821 - static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) 1384 + static int tomoyo_write_domain2(char *data, struct tomoyo_domain_info *domain, 1385 + const bool is_delete) 1386 + { 1387 + if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALLOW_MOUNT)) 1388 + return tomoyo_write_mount(data, domain, is_delete); 1389 + return tomoyo_write_file(data, domain, is_delete); 1390 + } 1391 + 1392 + /** 1393 + * tomoyo_write_domain - Write domain policy. 1394 + * 1395 + * @head: Pointer to "struct tomoyo_io_buffer". 1396 + * 1397 + * Returns 0 on success, negative value otherwise. 1398 + * 1399 + * Caller holds tomoyo_read_lock(). 1400 + */ 1401 + static int tomoyo_write_domain(struct tomoyo_io_buffer *head) 822 1402 { 823 1403 char *data = head->write_buf; 824 1404 struct tomoyo_domain_info *domain = head->write_var1; ··· 847 1393 is_delete = true; 848 1394 else if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_SELECT)) 849 1395 is_select = true; 850 - if (is_select && tomoyo_is_select_one(head, data)) 1396 + if (is_select && tomoyo_select_one(head, data)) 851 1397 return 0; 852 1398 /* Don't allow updating policies by non manager programs. */ 853 - if (!tomoyo_is_policy_manager()) 1399 + if (!tomoyo_manager()) 854 1400 return -EPERM; 855 - if (tomoyo_is_domain_def(data)) { 1401 + if (tomoyo_domain_def(data)) { 856 1402 domain = NULL; 857 1403 if (is_delete) 858 1404 tomoyo_delete_domain(data); 859 1405 else if (is_select) 860 1406 domain = tomoyo_find_domain(data); 861 1407 else 862 - domain = tomoyo_find_or_assign_new_domain(data, 0); 1408 + domain = tomoyo_assign_domain(data, 0); 863 1409 head->write_var1 = domain; 864 1410 return 0; 865 1411 } ··· 876 1422 domain->ignore_global_allow_read = !is_delete; 877 1423 return 0; 878 1424 } 879 - return tomoyo_write_file_policy(data, domain, is_delete); 1425 + if (!strcmp(data, TOMOYO_KEYWORD_QUOTA_EXCEEDED)) { 1426 + domain->quota_warned = !is_delete; 1427 + return 0; 1428 + } 1429 + if (!strcmp(data, TOMOYO_KEYWORD_TRANSITION_FAILED)) { 1430 + domain->transition_failed = !is_delete; 1431 + return 0; 1432 + } 1433 + return tomoyo_write_domain2(data, domain, is_delete); 880 1434 } 881 1435 882 1436 /** 883 - * tomoyo_print_path_acl - Print a single path ACL entry. 1437 + * tomoyo_fns - Find next set bit. 884 1438 * 885 - * @head: Pointer to "struct tomoyo_io_buffer". 886 - * @ptr: Pointer to "struct tomoyo_path_acl". 1439 + * @perm: 8 bits value. 1440 + * @bit: First bit to find. 887 1441 * 888 - * Returns true on success, false otherwise. 1442 + * Returns next on-bit on success, 8 otherwise. 889 1443 */ 890 - static bool tomoyo_print_path_acl(struct tomoyo_io_buffer *head, 891 - struct tomoyo_path_acl *ptr) 1444 + static u8 tomoyo_fns(const u8 perm, u8 bit) 892 1445 { 893 - int pos; 894 - u8 bit; 895 - const u32 perm = ptr->perm | (((u32) ptr->perm_high) << 16); 896 - 897 - for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_OPERATION; bit++) { 898 - if (!(perm & (1 << bit))) 899 - continue; 900 - /* Print "read/write" instead of "read" and "write". */ 901 - if ((bit == TOMOYO_TYPE_READ || bit == TOMOYO_TYPE_WRITE) 902 - && (perm & (1 << TOMOYO_TYPE_READ_WRITE))) 903 - continue; 904 - pos = head->read_avail; 905 - if (!tomoyo_io_printf(head, "allow_%s ", 906 - tomoyo_path2keyword(bit)) || 907 - !tomoyo_print_name_union(head, &ptr->name) || 908 - !tomoyo_io_printf(head, "\n")) 909 - goto out; 910 - } 911 - head->read_bit = 0; 912 - return true; 913 - out: 914 - head->read_bit = bit; 915 - head->read_avail = pos; 916 - return false; 917 - } 918 - 919 - /** 920 - * tomoyo_print_path2_acl - Print a double path ACL entry. 921 - * 922 - * @head: Pointer to "struct tomoyo_io_buffer". 923 - * @ptr: Pointer to "struct tomoyo_path2_acl". 924 - * 925 - * Returns true on success, false otherwise. 926 - */ 927 - static bool tomoyo_print_path2_acl(struct tomoyo_io_buffer *head, 928 - struct tomoyo_path2_acl *ptr) 929 - { 930 - int pos; 931 - const u8 perm = ptr->perm; 932 - u8 bit; 933 - 934 - for (bit = head->read_bit; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) { 935 - if (!(perm & (1 << bit))) 936 - continue; 937 - pos = head->read_avail; 938 - if (!tomoyo_io_printf(head, "allow_%s ", 939 - tomoyo_path22keyword(bit)) || 940 - !tomoyo_print_name_union(head, &ptr->name1) || 941 - !tomoyo_print_name_union(head, &ptr->name2) || 942 - !tomoyo_io_printf(head, "\n")) 943 - goto out; 944 - } 945 - head->read_bit = 0; 946 - return true; 947 - out: 948 - head->read_bit = bit; 949 - head->read_avail = pos; 950 - return false; 1446 + for ( ; bit < 8; bit++) 1447 + if (perm & (1 << bit)) 1448 + break; 1449 + return bit; 951 1450 } 952 1451 953 1452 /** 954 1453 * tomoyo_print_entry - Print an ACL entry. 955 1454 * 956 1455 * @head: Pointer to "struct tomoyo_io_buffer". 957 - * @ptr: Pointer to an ACL entry. 1456 + * @acl: Pointer to an ACL entry. 958 1457 * 959 1458 * Returns true on success, false otherwise. 960 1459 */ 961 1460 static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, 962 - struct tomoyo_acl_info *ptr) 1461 + struct tomoyo_acl_info *acl) 963 1462 { 964 - const u8 acl_type = ptr->type; 1463 + const u8 acl_type = acl->type; 1464 + u8 bit; 965 1465 966 - if (acl_type == TOMOYO_TYPE_PATH_ACL) { 967 - struct tomoyo_path_acl *acl 968 - = container_of(ptr, struct tomoyo_path_acl, head); 969 - return tomoyo_print_path_acl(head, acl); 1466 + if (acl->is_deleted) 1467 + return true; 1468 + next: 1469 + bit = head->r.bit; 1470 + if (!tomoyo_flush(head)) 1471 + return false; 1472 + else if (acl_type == TOMOYO_TYPE_PATH_ACL) { 1473 + struct tomoyo_path_acl *ptr = 1474 + container_of(acl, typeof(*ptr), head); 1475 + const u16 perm = ptr->perm; 1476 + for ( ; bit < TOMOYO_MAX_PATH_OPERATION; bit++) { 1477 + if (!(perm & (1 << bit))) 1478 + continue; 1479 + if (head->r.print_execute_only && 1480 + bit != TOMOYO_TYPE_EXECUTE) 1481 + continue; 1482 + /* Print "read/write" instead of "read" and "write". */ 1483 + if ((bit == TOMOYO_TYPE_READ || 1484 + bit == TOMOYO_TYPE_WRITE) 1485 + && (perm & (1 << TOMOYO_TYPE_READ_WRITE))) 1486 + continue; 1487 + break; 1488 + } 1489 + if (bit >= TOMOYO_MAX_PATH_OPERATION) 1490 + goto done; 1491 + tomoyo_io_printf(head, "allow_%s", tomoyo_path_keyword[bit]); 1492 + tomoyo_print_name_union(head, &ptr->name); 1493 + } else if (head->r.print_execute_only) { 1494 + return true; 1495 + } else if (acl_type == TOMOYO_TYPE_PATH2_ACL) { 1496 + struct tomoyo_path2_acl *ptr = 1497 + container_of(acl, typeof(*ptr), head); 1498 + bit = tomoyo_fns(ptr->perm, bit); 1499 + if (bit >= TOMOYO_MAX_PATH2_OPERATION) 1500 + goto done; 1501 + tomoyo_io_printf(head, "allow_%s", tomoyo_path2_keyword[bit]); 1502 + tomoyo_print_name_union(head, &ptr->name1); 1503 + tomoyo_print_name_union(head, &ptr->name2); 1504 + } else if (acl_type == TOMOYO_TYPE_PATH_NUMBER_ACL) { 1505 + struct tomoyo_path_number_acl *ptr = 1506 + container_of(acl, typeof(*ptr), head); 1507 + bit = tomoyo_fns(ptr->perm, bit); 1508 + if (bit >= TOMOYO_MAX_PATH_NUMBER_OPERATION) 1509 + goto done; 1510 + tomoyo_io_printf(head, "allow_%s", 1511 + tomoyo_path_number_keyword[bit]); 1512 + tomoyo_print_name_union(head, &ptr->name); 1513 + tomoyo_print_number_union(head, &ptr->number); 1514 + } else if (acl_type == TOMOYO_TYPE_MKDEV_ACL) { 1515 + struct tomoyo_mkdev_acl *ptr = 1516 + container_of(acl, typeof(*ptr), head); 1517 + bit = tomoyo_fns(ptr->perm, bit); 1518 + if (bit >= TOMOYO_MAX_MKDEV_OPERATION) 1519 + goto done; 1520 + tomoyo_io_printf(head, "allow_%s", tomoyo_mkdev_keyword[bit]); 1521 + tomoyo_print_name_union(head, &ptr->name); 1522 + tomoyo_print_number_union(head, &ptr->mode); 1523 + tomoyo_print_number_union(head, &ptr->major); 1524 + tomoyo_print_number_union(head, &ptr->minor); 1525 + } else if (acl_type == TOMOYO_TYPE_MOUNT_ACL) { 1526 + struct tomoyo_mount_acl *ptr = 1527 + container_of(acl, typeof(*ptr), head); 1528 + tomoyo_io_printf(head, "allow_mount"); 1529 + tomoyo_print_name_union(head, &ptr->dev_name); 1530 + tomoyo_print_name_union(head, &ptr->dir_name); 1531 + tomoyo_print_name_union(head, &ptr->fs_type); 1532 + tomoyo_print_number_union(head, &ptr->flags); 970 1533 } 971 - if (acl_type == TOMOYO_TYPE_PATH2_ACL) { 972 - struct tomoyo_path2_acl *acl 973 - = container_of(ptr, struct tomoyo_path2_acl, head); 974 - return tomoyo_print_path2_acl(head, acl); 975 - } 976 - BUG(); /* This must not happen. */ 977 - return false; 1534 + head->r.bit = bit + 1; 1535 + tomoyo_io_printf(head, "\n"); 1536 + if (acl_type != TOMOYO_TYPE_MOUNT_ACL) 1537 + goto next; 1538 + done: 1539 + head->r.bit = 0; 1540 + return true; 978 1541 } 979 1542 980 1543 /** 981 - * tomoyo_read_domain_policy - Read domain policy. 1544 + * tomoyo_read_domain2 - Read domain policy. 1545 + * 1546 + * @head: Pointer to "struct tomoyo_io_buffer". 1547 + * @domain: Pointer to "struct tomoyo_domain_info". 1548 + * 1549 + * Caller holds tomoyo_read_lock(). 1550 + * 1551 + * Returns true on success, false otherwise. 1552 + */ 1553 + static bool tomoyo_read_domain2(struct tomoyo_io_buffer *head, 1554 + struct tomoyo_domain_info *domain) 1555 + { 1556 + list_for_each_cookie(head->r.acl, &domain->acl_info_list) { 1557 + struct tomoyo_acl_info *ptr = 1558 + list_entry(head->r.acl, typeof(*ptr), list); 1559 + if (!tomoyo_print_entry(head, ptr)) 1560 + return false; 1561 + } 1562 + head->r.acl = NULL; 1563 + return true; 1564 + } 1565 + 1566 + /** 1567 + * tomoyo_read_domain - Read domain policy. 982 1568 * 983 1569 * @head: Pointer to "struct tomoyo_io_buffer". 984 1570 * 985 - * Returns 0. 986 - * 987 1571 * Caller holds tomoyo_read_lock(). 988 1572 */ 989 - static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) 1573 + static void tomoyo_read_domain(struct tomoyo_io_buffer *head) 990 1574 { 991 - struct list_head *dpos; 992 - struct list_head *apos; 993 - bool done = true; 994 - 995 - if (head->read_eof) 996 - return 0; 997 - if (head->read_step == 0) 998 - head->read_step = 1; 999 - list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) { 1000 - struct tomoyo_domain_info *domain; 1001 - const char *quota_exceeded = ""; 1002 - const char *transition_failed = ""; 1003 - const char *ignore_global_allow_read = ""; 1004 - domain = list_entry(dpos, struct tomoyo_domain_info, list); 1005 - if (head->read_step != 1) 1006 - goto acl_loop; 1007 - if (domain->is_deleted && !head->read_single_domain) 1008 - continue; 1009 - /* Print domainname and flags. */ 1010 - if (domain->quota_warned) 1011 - quota_exceeded = "quota_exceeded\n"; 1012 - if (domain->transition_failed) 1013 - transition_failed = "transition_failed\n"; 1014 - if (domain->ignore_global_allow_read) 1015 - ignore_global_allow_read 1016 - = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n"; 1017 - done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE 1018 - "%u\n%s%s%s\n", 1019 - domain->domainname->name, 1020 - domain->profile, quota_exceeded, 1021 - transition_failed, 1022 - ignore_global_allow_read); 1023 - if (!done) 1024 - break; 1025 - head->read_step = 2; 1026 - acl_loop: 1027 - if (head->read_step == 3) 1028 - goto tail_mark; 1029 - /* Print ACL entries in the domain. */ 1030 - list_for_each_cookie(apos, head->read_var2, 1031 - &domain->acl_info_list) { 1032 - struct tomoyo_acl_info *ptr 1033 - = list_entry(apos, struct tomoyo_acl_info, 1034 - list); 1035 - done = tomoyo_print_entry(head, ptr); 1036 - if (!done) 1037 - break; 1575 + if (head->r.eof) 1576 + return; 1577 + list_for_each_cookie(head->r.domain, &tomoyo_domain_list) { 1578 + struct tomoyo_domain_info *domain = 1579 + list_entry(head->r.domain, typeof(*domain), list); 1580 + switch (head->r.step) { 1581 + case 0: 1582 + if (domain->is_deleted && 1583 + !head->r.print_this_domain_only) 1584 + continue; 1585 + /* Print domainname and flags. */ 1586 + tomoyo_set_string(head, domain->domainname->name); 1587 + tomoyo_set_lf(head); 1588 + tomoyo_io_printf(head, 1589 + TOMOYO_KEYWORD_USE_PROFILE "%u\n", 1590 + domain->profile); 1591 + if (domain->quota_warned) 1592 + tomoyo_set_string(head, "quota_exceeded\n"); 1593 + if (domain->transition_failed) 1594 + tomoyo_set_string(head, "transition_failed\n"); 1595 + if (domain->ignore_global_allow_read) 1596 + tomoyo_set_string(head, 1597 + TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ 1598 + "\n"); 1599 + head->r.step++; 1600 + tomoyo_set_lf(head); 1601 + /* fall through */ 1602 + case 1: 1603 + if (!tomoyo_read_domain2(head, domain)) 1604 + return; 1605 + head->r.step++; 1606 + if (!tomoyo_set_lf(head)) 1607 + return; 1608 + /* fall through */ 1609 + case 2: 1610 + head->r.step = 0; 1611 + if (head->r.print_this_domain_only) 1612 + goto done; 1038 1613 } 1039 - if (!done) 1040 - break; 1041 - head->read_step = 3; 1042 - tail_mark: 1043 - done = tomoyo_io_printf(head, "\n"); 1044 - if (!done) 1045 - break; 1046 - head->read_step = 1; 1047 - if (head->read_single_domain) 1048 - break; 1049 1614 } 1050 - head->read_eof = done; 1051 - return 0; 1615 + done: 1616 + head->r.eof = true; 1052 1617 } 1053 1618 1054 1619 /** ··· 1080 1607 * This is equivalent to doing 1081 1608 * 1082 1609 * ( echo "select " $domainname; echo "use_profile " $profile ) | 1083 - * /usr/lib/ccs/loadpolicy -d 1610 + * /usr/sbin/tomoyo-loadpolicy -d 1084 1611 * 1085 1612 * Caller holds tomoyo_read_lock(). 1086 1613 */ ··· 1119 1646 * 1120 1647 * Caller holds tomoyo_read_lock(). 1121 1648 */ 1122 - static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head) 1649 + static void tomoyo_read_domain_profile(struct tomoyo_io_buffer *head) 1123 1650 { 1124 - struct list_head *pos; 1125 - bool done = true; 1126 - 1127 - if (head->read_eof) 1128 - return 0; 1129 - list_for_each_cookie(pos, head->read_var1, &tomoyo_domain_list) { 1130 - struct tomoyo_domain_info *domain; 1131 - domain = list_entry(pos, struct tomoyo_domain_info, list); 1651 + if (head->r.eof) 1652 + return; 1653 + list_for_each_cookie(head->r.domain, &tomoyo_domain_list) { 1654 + struct tomoyo_domain_info *domain = 1655 + list_entry(head->r.domain, typeof(*domain), list); 1132 1656 if (domain->is_deleted) 1133 1657 continue; 1134 - done = tomoyo_io_printf(head, "%u %s\n", domain->profile, 1135 - domain->domainname->name); 1136 - if (!done) 1137 - break; 1658 + if (!tomoyo_flush(head)) 1659 + return; 1660 + tomoyo_io_printf(head, "%u ", domain->profile); 1661 + tomoyo_set_string(head, domain->domainname->name); 1662 + tomoyo_set_lf(head); 1138 1663 } 1139 - head->read_eof = done; 1140 - return 0; 1664 + head->r.eof = true; 1141 1665 } 1142 1666 1143 1667 /** ··· 1146 1676 */ 1147 1677 static int tomoyo_write_pid(struct tomoyo_io_buffer *head) 1148 1678 { 1149 - unsigned long pid; 1150 - /* No error check. */ 1151 - strict_strtoul(head->write_buf, 10, &pid); 1152 - head->read_step = (int) pid; 1153 - head->read_eof = false; 1679 + head->r.eof = false; 1154 1680 return 0; 1155 1681 } 1156 1682 ··· 1160 1694 * The PID is specified by tomoyo_write_pid() so that the user can obtain 1161 1695 * using read()/write() interface rather than sysctl() interface. 1162 1696 */ 1163 - static int tomoyo_read_pid(struct tomoyo_io_buffer *head) 1697 + static void tomoyo_read_pid(struct tomoyo_io_buffer *head) 1164 1698 { 1165 - if (head->read_avail == 0 && !head->read_eof) { 1166 - const int pid = head->read_step; 1167 - struct task_struct *p; 1168 - struct tomoyo_domain_info *domain = NULL; 1169 - rcu_read_lock(); 1170 - read_lock(&tasklist_lock); 1171 - p = find_task_by_vpid(pid); 1172 - if (p) 1173 - domain = tomoyo_real_domain(p); 1174 - read_unlock(&tasklist_lock); 1175 - rcu_read_unlock(); 1176 - if (domain) 1177 - tomoyo_io_printf(head, "%d %u %s", pid, domain->profile, 1178 - domain->domainname->name); 1179 - head->read_eof = true; 1699 + char *buf = head->write_buf; 1700 + bool global_pid = false; 1701 + unsigned int pid; 1702 + struct task_struct *p; 1703 + struct tomoyo_domain_info *domain = NULL; 1704 + 1705 + /* Accessing write_buf is safe because head->io_sem is held. */ 1706 + if (!buf) { 1707 + head->r.eof = true; 1708 + return; /* Do nothing if open(O_RDONLY). */ 1180 1709 } 1181 - return 0; 1710 + if (head->r.w_pos || head->r.eof) 1711 + return; 1712 + head->r.eof = true; 1713 + if (tomoyo_str_starts(&buf, "global-pid ")) 1714 + global_pid = true; 1715 + pid = (unsigned int) simple_strtoul(buf, NULL, 10); 1716 + rcu_read_lock(); 1717 + read_lock(&tasklist_lock); 1718 + if (global_pid) 1719 + p = find_task_by_pid_ns(pid, &init_pid_ns); 1720 + else 1721 + p = find_task_by_vpid(pid); 1722 + if (p) 1723 + domain = tomoyo_real_domain(p); 1724 + read_unlock(&tasklist_lock); 1725 + rcu_read_unlock(); 1726 + if (!domain) 1727 + return; 1728 + tomoyo_io_printf(head, "%u %u ", pid, domain->profile); 1729 + tomoyo_set_string(head, domain->domainname->name); 1182 1730 } 1183 1731 1732 + static const char *tomoyo_transition_type[TOMOYO_MAX_TRANSITION_TYPE] = { 1733 + [TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE] 1734 + = TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN, 1735 + [TOMOYO_TRANSITION_CONTROL_INITIALIZE] 1736 + = TOMOYO_KEYWORD_INITIALIZE_DOMAIN, 1737 + [TOMOYO_TRANSITION_CONTROL_NO_KEEP] = TOMOYO_KEYWORD_NO_KEEP_DOMAIN, 1738 + [TOMOYO_TRANSITION_CONTROL_KEEP] = TOMOYO_KEYWORD_KEEP_DOMAIN 1739 + }; 1740 + 1741 + static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = { 1742 + [TOMOYO_PATH_GROUP] = TOMOYO_KEYWORD_PATH_GROUP, 1743 + [TOMOYO_NUMBER_GROUP] = TOMOYO_KEYWORD_NUMBER_GROUP 1744 + }; 1745 + 1184 1746 /** 1185 - * tomoyo_write_exception_policy - Write exception policy. 1747 + * tomoyo_write_exception - Write exception policy. 1186 1748 * 1187 1749 * @head: Pointer to "struct tomoyo_io_buffer". 1188 1750 * ··· 1218 1724 * 1219 1725 * Caller holds tomoyo_read_lock(). 1220 1726 */ 1221 - static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) 1727 + static int tomoyo_write_exception(struct tomoyo_io_buffer *head) 1222 1728 { 1223 1729 char *data = head->write_buf; 1224 1730 bool is_delete = tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE); 1731 + u8 i; 1732 + static const struct { 1733 + const char *keyword; 1734 + int (*write) (char *, const bool); 1735 + } tomoyo_callback[4] = { 1736 + { TOMOYO_KEYWORD_AGGREGATOR, tomoyo_write_aggregator }, 1737 + { TOMOYO_KEYWORD_FILE_PATTERN, tomoyo_write_pattern }, 1738 + { TOMOYO_KEYWORD_DENY_REWRITE, tomoyo_write_no_rewrite }, 1739 + { TOMOYO_KEYWORD_ALLOW_READ, tomoyo_write_globally_readable }, 1740 + }; 1225 1741 1226 - if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_KEEP_DOMAIN)) 1227 - return tomoyo_write_domain_keeper_policy(data, false, 1228 - is_delete); 1229 - if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NO_KEEP_DOMAIN)) 1230 - return tomoyo_write_domain_keeper_policy(data, true, is_delete); 1231 - if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_INITIALIZE_DOMAIN)) 1232 - return tomoyo_write_domain_initializer_policy(data, false, 1233 - is_delete); 1234 - if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN)) 1235 - return tomoyo_write_domain_initializer_policy(data, true, 1236 - is_delete); 1237 - if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALIAS)) 1238 - return tomoyo_write_alias_policy(data, is_delete); 1239 - if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALLOW_READ)) 1240 - return tomoyo_write_globally_readable_policy(data, is_delete); 1241 - if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_FILE_PATTERN)) 1242 - return tomoyo_write_pattern_policy(data, is_delete); 1243 - if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DENY_REWRITE)) 1244 - return tomoyo_write_no_rewrite_policy(data, is_delete); 1245 - if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_PATH_GROUP)) 1246 - return tomoyo_write_path_group_policy(data, is_delete); 1742 + for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++) 1743 + if (tomoyo_str_starts(&data, tomoyo_transition_type[i])) 1744 + return tomoyo_write_transition_control(data, is_delete, 1745 + i); 1746 + for (i = 0; i < 4; i++) 1747 + if (tomoyo_str_starts(&data, tomoyo_callback[i].keyword)) 1748 + return tomoyo_callback[i].write(data, is_delete); 1749 + for (i = 0; i < TOMOYO_MAX_GROUP; i++) 1750 + if (tomoyo_str_starts(&data, tomoyo_group_name[i])) 1751 + return tomoyo_write_group(data, is_delete, i); 1247 1752 return -EINVAL; 1248 1753 } 1249 1754 1250 1755 /** 1251 - * tomoyo_read_exception_policy - Read exception policy. 1756 + * tomoyo_read_group - Read "struct tomoyo_path_group"/"struct tomoyo_number_group" list. 1252 1757 * 1253 1758 * @head: Pointer to "struct tomoyo_io_buffer". 1759 + * @idx: Index number. 1254 1760 * 1255 - * Returns 0 on success, -EINVAL otherwise. 1761 + * Returns true on success, false otherwise. 1256 1762 * 1257 1763 * Caller holds tomoyo_read_lock(). 1258 1764 */ 1259 - static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head) 1765 + static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx) 1260 1766 { 1261 - if (!head->read_eof) { 1262 - switch (head->read_step) { 1263 - case 0: 1264 - head->read_var2 = NULL; 1265 - head->read_step = 1; 1266 - case 1: 1267 - if (!tomoyo_read_domain_keeper_policy(head)) 1268 - break; 1269 - head->read_var2 = NULL; 1270 - head->read_step = 2; 1271 - case 2: 1272 - if (!tomoyo_read_globally_readable_policy(head)) 1273 - break; 1274 - head->read_var2 = NULL; 1275 - head->read_step = 3; 1276 - case 3: 1277 - head->read_var2 = NULL; 1278 - head->read_step = 4; 1279 - case 4: 1280 - if (!tomoyo_read_domain_initializer_policy(head)) 1281 - break; 1282 - head->read_var2 = NULL; 1283 - head->read_step = 5; 1284 - case 5: 1285 - if (!tomoyo_read_alias_policy(head)) 1286 - break; 1287 - head->read_var2 = NULL; 1288 - head->read_step = 6; 1289 - case 6: 1290 - head->read_var2 = NULL; 1291 - head->read_step = 7; 1292 - case 7: 1293 - if (!tomoyo_read_file_pattern(head)) 1294 - break; 1295 - head->read_var2 = NULL; 1296 - head->read_step = 8; 1297 - case 8: 1298 - if (!tomoyo_read_no_rewrite_policy(head)) 1299 - break; 1300 - head->read_var2 = NULL; 1301 - head->read_step = 9; 1302 - case 9: 1303 - if (!tomoyo_read_path_group_policy(head)) 1304 - break; 1305 - head->read_var1 = NULL; 1306 - head->read_var2 = NULL; 1307 - head->read_step = 10; 1308 - case 10: 1309 - head->read_eof = true; 1310 - break; 1311 - default: 1312 - return -EINVAL; 1767 + list_for_each_cookie(head->r.group, &tomoyo_group_list[idx]) { 1768 + struct tomoyo_group *group = 1769 + list_entry(head->r.group, typeof(*group), list); 1770 + list_for_each_cookie(head->r.acl, &group->member_list) { 1771 + struct tomoyo_acl_head *ptr = 1772 + list_entry(head->r.acl, typeof(*ptr), list); 1773 + if (ptr->is_deleted) 1774 + continue; 1775 + if (!tomoyo_flush(head)) 1776 + return false; 1777 + tomoyo_set_string(head, tomoyo_group_name[idx]); 1778 + tomoyo_set_string(head, group->group_name->name); 1779 + if (idx == TOMOYO_PATH_GROUP) { 1780 + tomoyo_set_space(head); 1781 + tomoyo_set_string(head, container_of 1782 + (ptr, struct tomoyo_path_group, 1783 + head)->member_name->name); 1784 + } else if (idx == TOMOYO_NUMBER_GROUP) { 1785 + tomoyo_print_number_union(head, &container_of 1786 + (ptr, 1787 + struct tomoyo_number_group, 1788 + head)->number); 1789 + } 1790 + tomoyo_set_lf(head); 1313 1791 } 1792 + head->r.acl = NULL; 1314 1793 } 1315 - return 0; 1316 - } 1317 - 1318 - /* path to policy loader */ 1319 - static const char *tomoyo_loader = "/sbin/tomoyo-init"; 1320 - 1321 - /** 1322 - * tomoyo_policy_loader_exists - Check whether /sbin/tomoyo-init exists. 1323 - * 1324 - * Returns true if /sbin/tomoyo-init exists, false otherwise. 1325 - */ 1326 - static bool tomoyo_policy_loader_exists(void) 1327 - { 1328 - /* 1329 - * Don't activate MAC if the policy loader doesn't exist. 1330 - * If the initrd includes /sbin/init but real-root-dev has not 1331 - * mounted on / yet, activating MAC will block the system since 1332 - * policies are not loaded yet. 1333 - * Thus, let do_execve() call this function everytime. 1334 - */ 1335 - struct path path; 1336 - 1337 - if (kern_path(tomoyo_loader, LOOKUP_FOLLOW, &path)) { 1338 - printk(KERN_INFO "Not activating Mandatory Access Control now " 1339 - "since %s doesn't exist.\n", tomoyo_loader); 1340 - return false; 1341 - } 1342 - path_put(&path); 1794 + head->r.group = NULL; 1343 1795 return true; 1344 1796 } 1345 1797 1346 1798 /** 1347 - * tomoyo_load_policy - Run external policy loader to load policy. 1799 + * tomoyo_read_policy - Read "struct tomoyo_..._entry" list. 1348 1800 * 1349 - * @filename: The program about to start. 1801 + * @head: Pointer to "struct tomoyo_io_buffer". 1802 + * @idx: Index number. 1350 1803 * 1351 - * This function checks whether @filename is /sbin/init , and if so 1352 - * invoke /sbin/tomoyo-init and wait for the termination of /sbin/tomoyo-init 1353 - * and then continues invocation of /sbin/init. 1354 - * /sbin/tomoyo-init reads policy files in /etc/tomoyo/ directory and 1355 - * writes to /sys/kernel/security/tomoyo/ interfaces. 1804 + * Returns true on success, false otherwise. 1356 1805 * 1357 - * Returns nothing. 1806 + * Caller holds tomoyo_read_lock(). 1358 1807 */ 1359 - void tomoyo_load_policy(const char *filename) 1808 + static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) 1360 1809 { 1361 - char *argv[2]; 1362 - char *envp[3]; 1363 - 1364 - if (tomoyo_policy_loaded) 1365 - return; 1366 - /* 1367 - * Check filename is /sbin/init or /sbin/tomoyo-start. 1368 - * /sbin/tomoyo-start is a dummy filename in case where /sbin/init can't 1369 - * be passed. 1370 - * You can create /sbin/tomoyo-start by 1371 - * "ln -s /bin/true /sbin/tomoyo-start". 1372 - */ 1373 - if (strcmp(filename, "/sbin/init") && 1374 - strcmp(filename, "/sbin/tomoyo-start")) 1375 - return; 1376 - if (!tomoyo_policy_loader_exists()) 1377 - return; 1378 - 1379 - printk(KERN_INFO "Calling %s to load policy. Please wait.\n", 1380 - tomoyo_loader); 1381 - argv[0] = (char *) tomoyo_loader; 1382 - argv[1] = NULL; 1383 - envp[0] = "HOME=/"; 1384 - envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; 1385 - envp[2] = NULL; 1386 - call_usermodehelper(argv[0], argv, envp, 1); 1387 - 1388 - printk(KERN_INFO "TOMOYO: 2.2.0 2009/04/01\n"); 1389 - printk(KERN_INFO "Mandatory Access Control activated.\n"); 1390 - tomoyo_policy_loaded = true; 1391 - { /* Check all profiles currently assigned to domains are defined. */ 1392 - struct tomoyo_domain_info *domain; 1393 - list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { 1394 - const u8 profile = domain->profile; 1395 - if (tomoyo_profile_ptr[profile]) 1396 - continue; 1397 - panic("Profile %u (used by '%s') not defined.\n", 1398 - profile, domain->domainname->name); 1810 + list_for_each_cookie(head->r.acl, &tomoyo_policy_list[idx]) { 1811 + struct tomoyo_acl_head *acl = 1812 + container_of(head->r.acl, typeof(*acl), list); 1813 + if (acl->is_deleted) 1814 + continue; 1815 + if (!tomoyo_flush(head)) 1816 + return false; 1817 + switch (idx) { 1818 + case TOMOYO_ID_TRANSITION_CONTROL: 1819 + { 1820 + struct tomoyo_transition_control *ptr = 1821 + container_of(acl, typeof(*ptr), head); 1822 + tomoyo_set_string(head, 1823 + tomoyo_transition_type 1824 + [ptr->type]); 1825 + if (ptr->program) 1826 + tomoyo_set_string(head, 1827 + ptr->program->name); 1828 + if (ptr->program && ptr->domainname) 1829 + tomoyo_set_string(head, " from "); 1830 + if (ptr->domainname) 1831 + tomoyo_set_string(head, 1832 + ptr->domainname-> 1833 + name); 1834 + } 1835 + break; 1836 + case TOMOYO_ID_GLOBALLY_READABLE: 1837 + { 1838 + struct tomoyo_readable_file *ptr = 1839 + container_of(acl, typeof(*ptr), head); 1840 + tomoyo_set_string(head, 1841 + TOMOYO_KEYWORD_ALLOW_READ); 1842 + tomoyo_set_string(head, ptr->filename->name); 1843 + } 1844 + break; 1845 + case TOMOYO_ID_AGGREGATOR: 1846 + { 1847 + struct tomoyo_aggregator *ptr = 1848 + container_of(acl, typeof(*ptr), head); 1849 + tomoyo_set_string(head, 1850 + TOMOYO_KEYWORD_AGGREGATOR); 1851 + tomoyo_set_string(head, 1852 + ptr->original_name->name); 1853 + tomoyo_set_space(head); 1854 + tomoyo_set_string(head, 1855 + ptr->aggregated_name->name); 1856 + } 1857 + break; 1858 + case TOMOYO_ID_PATTERN: 1859 + { 1860 + struct tomoyo_no_pattern *ptr = 1861 + container_of(acl, typeof(*ptr), head); 1862 + tomoyo_set_string(head, 1863 + TOMOYO_KEYWORD_FILE_PATTERN); 1864 + tomoyo_set_string(head, ptr->pattern->name); 1865 + } 1866 + break; 1867 + case TOMOYO_ID_NO_REWRITE: 1868 + { 1869 + struct tomoyo_no_rewrite *ptr = 1870 + container_of(acl, typeof(*ptr), head); 1871 + tomoyo_set_string(head, 1872 + TOMOYO_KEYWORD_DENY_REWRITE); 1873 + tomoyo_set_string(head, ptr->pattern->name); 1874 + } 1875 + break; 1876 + default: 1877 + continue; 1399 1878 } 1879 + tomoyo_set_lf(head); 1400 1880 } 1881 + head->r.acl = NULL; 1882 + return true; 1883 + } 1884 + 1885 + /** 1886 + * tomoyo_read_exception - Read exception policy. 1887 + * 1888 + * @head: Pointer to "struct tomoyo_io_buffer". 1889 + * 1890 + * Caller holds tomoyo_read_lock(). 1891 + */ 1892 + static void tomoyo_read_exception(struct tomoyo_io_buffer *head) 1893 + { 1894 + if (head->r.eof) 1895 + return; 1896 + while (head->r.step < TOMOYO_MAX_POLICY && 1897 + tomoyo_read_policy(head, head->r.step)) 1898 + head->r.step++; 1899 + if (head->r.step < TOMOYO_MAX_POLICY) 1900 + return; 1901 + while (head->r.step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP && 1902 + tomoyo_read_group(head, head->r.step - TOMOYO_MAX_POLICY)) 1903 + head->r.step++; 1904 + if (head->r.step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP) 1905 + return; 1906 + head->r.eof = true; 1907 + } 1908 + 1909 + /** 1910 + * tomoyo_print_header - Get header line of audit log. 1911 + * 1912 + * @r: Pointer to "struct tomoyo_request_info". 1913 + * 1914 + * Returns string representation. 1915 + * 1916 + * This function uses kmalloc(), so caller must kfree() if this function 1917 + * didn't return NULL. 1918 + */ 1919 + static char *tomoyo_print_header(struct tomoyo_request_info *r) 1920 + { 1921 + struct timeval tv; 1922 + const pid_t gpid = task_pid_nr(current); 1923 + static const int tomoyo_buffer_len = 4096; 1924 + char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS); 1925 + if (!buffer) 1926 + return NULL; 1927 + do_gettimeofday(&tv); 1928 + snprintf(buffer, tomoyo_buffer_len - 1, 1929 + "#timestamp=%lu profile=%u mode=%s (global-pid=%u)" 1930 + " task={ pid=%u ppid=%u uid=%u gid=%u euid=%u" 1931 + " egid=%u suid=%u sgid=%u fsuid=%u fsgid=%u }", 1932 + tv.tv_sec, r->profile, tomoyo_mode[r->mode], gpid, 1933 + (pid_t) sys_getpid(), (pid_t) sys_getppid(), 1934 + current_uid(), current_gid(), current_euid(), 1935 + current_egid(), current_suid(), current_sgid(), 1936 + current_fsuid(), current_fsgid()); 1937 + return buffer; 1938 + } 1939 + 1940 + /** 1941 + * tomoyo_init_audit_log - Allocate buffer for audit logs. 1942 + * 1943 + * @len: Required size. 1944 + * @r: Pointer to "struct tomoyo_request_info". 1945 + * 1946 + * Returns pointer to allocated memory. 1947 + * 1948 + * The @len is updated to add the header lines' size on success. 1949 + * 1950 + * This function uses kzalloc(), so caller must kfree() if this function 1951 + * didn't return NULL. 1952 + */ 1953 + static char *tomoyo_init_audit_log(int *len, struct tomoyo_request_info *r) 1954 + { 1955 + char *buf = NULL; 1956 + const char *header; 1957 + const char *domainname; 1958 + if (!r->domain) 1959 + r->domain = tomoyo_domain(); 1960 + domainname = r->domain->domainname->name; 1961 + header = tomoyo_print_header(r); 1962 + if (!header) 1963 + return NULL; 1964 + *len += strlen(domainname) + strlen(header) + 10; 1965 + buf = kzalloc(*len, GFP_NOFS); 1966 + if (buf) 1967 + snprintf(buf, (*len) - 1, "%s\n%s\n", header, domainname); 1968 + kfree(header); 1969 + return buf; 1970 + } 1971 + 1972 + /* Wait queue for tomoyo_query_list. */ 1973 + static DECLARE_WAIT_QUEUE_HEAD(tomoyo_query_wait); 1974 + 1975 + /* Lock for manipulating tomoyo_query_list. */ 1976 + static DEFINE_SPINLOCK(tomoyo_query_list_lock); 1977 + 1978 + /* Structure for query. */ 1979 + struct tomoyo_query { 1980 + struct list_head list; 1981 + char *query; 1982 + int query_len; 1983 + unsigned int serial; 1984 + int timer; 1985 + int answer; 1986 + }; 1987 + 1988 + /* The list for "struct tomoyo_query". */ 1989 + static LIST_HEAD(tomoyo_query_list); 1990 + 1991 + /* 1992 + * Number of "struct file" referring /sys/kernel/security/tomoyo/query 1993 + * interface. 1994 + */ 1995 + static atomic_t tomoyo_query_observers = ATOMIC_INIT(0); 1996 + 1997 + /** 1998 + * tomoyo_supervisor - Ask for the supervisor's decision. 1999 + * 2000 + * @r: Pointer to "struct tomoyo_request_info". 2001 + * @fmt: The printf()'s format string, followed by parameters. 2002 + * 2003 + * Returns 0 if the supervisor decided to permit the access request which 2004 + * violated the policy in enforcing mode, TOMOYO_RETRY_REQUEST if the 2005 + * supervisor decided to retry the access request which violated the policy in 2006 + * enforcing mode, 0 if it is not in enforcing mode, -EPERM otherwise. 2007 + */ 2008 + int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) 2009 + { 2010 + va_list args; 2011 + int error = -EPERM; 2012 + int pos; 2013 + int len; 2014 + static unsigned int tomoyo_serial; 2015 + struct tomoyo_query *entry = NULL; 2016 + bool quota_exceeded = false; 2017 + char *header; 2018 + switch (r->mode) { 2019 + char *buffer; 2020 + case TOMOYO_CONFIG_LEARNING: 2021 + if (!tomoyo_domain_quota_is_ok(r)) 2022 + return 0; 2023 + va_start(args, fmt); 2024 + len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 4; 2025 + va_end(args); 2026 + buffer = kmalloc(len, GFP_NOFS); 2027 + if (!buffer) 2028 + return 0; 2029 + va_start(args, fmt); 2030 + vsnprintf(buffer, len - 1, fmt, args); 2031 + va_end(args); 2032 + tomoyo_normalize_line(buffer); 2033 + tomoyo_write_domain2(buffer, r->domain, false); 2034 + kfree(buffer); 2035 + /* fall through */ 2036 + case TOMOYO_CONFIG_PERMISSIVE: 2037 + return 0; 2038 + } 2039 + if (!r->domain) 2040 + r->domain = tomoyo_domain(); 2041 + if (!atomic_read(&tomoyo_query_observers)) 2042 + return -EPERM; 2043 + va_start(args, fmt); 2044 + len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32; 2045 + va_end(args); 2046 + header = tomoyo_init_audit_log(&len, r); 2047 + if (!header) 2048 + goto out; 2049 + entry = kzalloc(sizeof(*entry), GFP_NOFS); 2050 + if (!entry) 2051 + goto out; 2052 + entry->query = kzalloc(len, GFP_NOFS); 2053 + if (!entry->query) 2054 + goto out; 2055 + len = ksize(entry->query); 2056 + spin_lock(&tomoyo_query_list_lock); 2057 + if (tomoyo_quota_for_query && tomoyo_query_memory_size + len + 2058 + sizeof(*entry) >= tomoyo_quota_for_query) { 2059 + quota_exceeded = true; 2060 + } else { 2061 + tomoyo_query_memory_size += len + sizeof(*entry); 2062 + entry->serial = tomoyo_serial++; 2063 + } 2064 + spin_unlock(&tomoyo_query_list_lock); 2065 + if (quota_exceeded) 2066 + goto out; 2067 + pos = snprintf(entry->query, len - 1, "Q%u-%hu\n%s", 2068 + entry->serial, r->retry, header); 2069 + kfree(header); 2070 + header = NULL; 2071 + va_start(args, fmt); 2072 + vsnprintf(entry->query + pos, len - 1 - pos, fmt, args); 2073 + entry->query_len = strlen(entry->query) + 1; 2074 + va_end(args); 2075 + spin_lock(&tomoyo_query_list_lock); 2076 + list_add_tail(&entry->list, &tomoyo_query_list); 2077 + spin_unlock(&tomoyo_query_list_lock); 2078 + /* Give 10 seconds for supervisor's opinion. */ 2079 + for (entry->timer = 0; 2080 + atomic_read(&tomoyo_query_observers) && entry->timer < 100; 2081 + entry->timer++) { 2082 + wake_up(&tomoyo_query_wait); 2083 + set_current_state(TASK_INTERRUPTIBLE); 2084 + schedule_timeout(HZ / 10); 2085 + if (entry->answer) 2086 + break; 2087 + } 2088 + spin_lock(&tomoyo_query_list_lock); 2089 + list_del(&entry->list); 2090 + tomoyo_query_memory_size -= len + sizeof(*entry); 2091 + spin_unlock(&tomoyo_query_list_lock); 2092 + switch (entry->answer) { 2093 + case 3: /* Asked to retry by administrator. */ 2094 + error = TOMOYO_RETRY_REQUEST; 2095 + r->retry++; 2096 + break; 2097 + case 1: 2098 + /* Granted by administrator. */ 2099 + error = 0; 2100 + break; 2101 + case 0: 2102 + /* Timed out. */ 2103 + break; 2104 + default: 2105 + /* Rejected by administrator. */ 2106 + break; 2107 + } 2108 + out: 2109 + if (entry) 2110 + kfree(entry->query); 2111 + kfree(entry); 2112 + kfree(header); 2113 + return error; 2114 + } 2115 + 2116 + /** 2117 + * tomoyo_poll_query - poll() for /sys/kernel/security/tomoyo/query. 2118 + * 2119 + * @file: Pointer to "struct file". 2120 + * @wait: Pointer to "poll_table". 2121 + * 2122 + * Returns POLLIN | POLLRDNORM when ready to read, 0 otherwise. 2123 + * 2124 + * Waits for access requests which violated policy in enforcing mode. 2125 + */ 2126 + static int tomoyo_poll_query(struct file *file, poll_table *wait) 2127 + { 2128 + struct list_head *tmp; 2129 + bool found = false; 2130 + u8 i; 2131 + for (i = 0; i < 2; i++) { 2132 + spin_lock(&tomoyo_query_list_lock); 2133 + list_for_each(tmp, &tomoyo_query_list) { 2134 + struct tomoyo_query *ptr = 2135 + list_entry(tmp, typeof(*ptr), list); 2136 + if (ptr->answer) 2137 + continue; 2138 + found = true; 2139 + break; 2140 + } 2141 + spin_unlock(&tomoyo_query_list_lock); 2142 + if (found) 2143 + return POLLIN | POLLRDNORM; 2144 + if (i) 2145 + break; 2146 + poll_wait(file, &tomoyo_query_wait, wait); 2147 + } 2148 + return 0; 2149 + } 2150 + 2151 + /** 2152 + * tomoyo_read_query - Read access requests which violated policy in enforcing mode. 2153 + * 2154 + * @head: Pointer to "struct tomoyo_io_buffer". 2155 + */ 2156 + static void tomoyo_read_query(struct tomoyo_io_buffer *head) 2157 + { 2158 + struct list_head *tmp; 2159 + int pos = 0; 2160 + int len = 0; 2161 + char *buf; 2162 + if (head->r.w_pos) 2163 + return; 2164 + if (head->read_buf) { 2165 + kfree(head->read_buf); 2166 + head->read_buf = NULL; 2167 + } 2168 + spin_lock(&tomoyo_query_list_lock); 2169 + list_for_each(tmp, &tomoyo_query_list) { 2170 + struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); 2171 + if (ptr->answer) 2172 + continue; 2173 + if (pos++ != head->r.query_index) 2174 + continue; 2175 + len = ptr->query_len; 2176 + break; 2177 + } 2178 + spin_unlock(&tomoyo_query_list_lock); 2179 + if (!len) { 2180 + head->r.query_index = 0; 2181 + return; 2182 + } 2183 + buf = kzalloc(len, GFP_NOFS); 2184 + if (!buf) 2185 + return; 2186 + pos = 0; 2187 + spin_lock(&tomoyo_query_list_lock); 2188 + list_for_each(tmp, &tomoyo_query_list) { 2189 + struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); 2190 + if (ptr->answer) 2191 + continue; 2192 + if (pos++ != head->r.query_index) 2193 + continue; 2194 + /* 2195 + * Some query can be skipped because tomoyo_query_list 2196 + * can change, but I don't care. 2197 + */ 2198 + if (len == ptr->query_len) 2199 + memmove(buf, ptr->query, len); 2200 + break; 2201 + } 2202 + spin_unlock(&tomoyo_query_list_lock); 2203 + if (buf[0]) { 2204 + head->read_buf = buf; 2205 + head->r.w[head->r.w_pos++] = buf; 2206 + head->r.query_index++; 2207 + } else { 2208 + kfree(buf); 2209 + } 2210 + } 2211 + 2212 + /** 2213 + * tomoyo_write_answer - Write the supervisor's decision. 2214 + * 2215 + * @head: Pointer to "struct tomoyo_io_buffer". 2216 + * 2217 + * Returns 0 on success, -EINVAL otherwise. 2218 + */ 2219 + static int tomoyo_write_answer(struct tomoyo_io_buffer *head) 2220 + { 2221 + char *data = head->write_buf; 2222 + struct list_head *tmp; 2223 + unsigned int serial; 2224 + unsigned int answer; 2225 + spin_lock(&tomoyo_query_list_lock); 2226 + list_for_each(tmp, &tomoyo_query_list) { 2227 + struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); 2228 + ptr->timer = 0; 2229 + } 2230 + spin_unlock(&tomoyo_query_list_lock); 2231 + if (sscanf(data, "A%u=%u", &serial, &answer) != 2) 2232 + return -EINVAL; 2233 + spin_lock(&tomoyo_query_list_lock); 2234 + list_for_each(tmp, &tomoyo_query_list) { 2235 + struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); 2236 + if (ptr->serial != serial) 2237 + continue; 2238 + if (!ptr->answer) 2239 + ptr->answer = answer; 2240 + break; 2241 + } 2242 + spin_unlock(&tomoyo_query_list_lock); 2243 + return 0; 1401 2244 } 1402 2245 1403 2246 /** ··· 1744 1913 * 1745 1914 * Returns version information. 1746 1915 */ 1747 - static int tomoyo_read_version(struct tomoyo_io_buffer *head) 1916 + static void tomoyo_read_version(struct tomoyo_io_buffer *head) 1748 1917 { 1749 - if (!head->read_eof) { 1750 - tomoyo_io_printf(head, "2.2.0"); 1751 - head->read_eof = true; 1918 + if (!head->r.eof) { 1919 + tomoyo_io_printf(head, "2.3.0"); 1920 + head->r.eof = true; 1752 1921 } 1753 - return 0; 1754 1922 } 1755 1923 1756 1924 /** ··· 1759 1929 * 1760 1930 * Returns the current process's domainname. 1761 1931 */ 1762 - static int tomoyo_read_self_domain(struct tomoyo_io_buffer *head) 1932 + static void tomoyo_read_self_domain(struct tomoyo_io_buffer *head) 1763 1933 { 1764 - if (!head->read_eof) { 1934 + if (!head->r.eof) { 1765 1935 /* 1766 1936 * tomoyo_domain()->domainname != NULL 1767 1937 * because every process belongs to a domain and 1768 1938 * the domain's name cannot be NULL. 1769 1939 */ 1770 1940 tomoyo_io_printf(head, "%s", tomoyo_domain()->domainname->name); 1771 - head->read_eof = true; 1941 + head->r.eof = true; 1772 1942 } 1773 - return 0; 1774 1943 } 1775 1944 1776 1945 /** ··· 1782 1953 * 1783 1954 * Caller acquires tomoyo_read_lock(). 1784 1955 */ 1785 - static int tomoyo_open_control(const u8 type, struct file *file) 1956 + int tomoyo_open_control(const u8 type, struct file *file) 1786 1957 { 1787 1958 struct tomoyo_io_buffer *head = kzalloc(sizeof(*head), GFP_NOFS); 1788 1959 1789 1960 if (!head) 1790 1961 return -ENOMEM; 1791 1962 mutex_init(&head->io_sem); 1963 + head->type = type; 1792 1964 switch (type) { 1793 1965 case TOMOYO_DOMAINPOLICY: 1794 1966 /* /sys/kernel/security/tomoyo/domain_policy */ 1795 - head->write = tomoyo_write_domain_policy; 1796 - head->read = tomoyo_read_domain_policy; 1967 + head->write = tomoyo_write_domain; 1968 + head->read = tomoyo_read_domain; 1797 1969 break; 1798 1970 case TOMOYO_EXCEPTIONPOLICY: 1799 1971 /* /sys/kernel/security/tomoyo/exception_policy */ 1800 - head->write = tomoyo_write_exception_policy; 1801 - head->read = tomoyo_read_exception_policy; 1972 + head->write = tomoyo_write_exception; 1973 + head->read = tomoyo_read_exception; 1802 1974 break; 1803 1975 case TOMOYO_SELFDOMAIN: 1804 1976 /* /sys/kernel/security/tomoyo/self_domain */ ··· 1831 2001 head->write = tomoyo_write_profile; 1832 2002 head->read = tomoyo_read_profile; 1833 2003 break; 2004 + case TOMOYO_QUERY: /* /sys/kernel/security/tomoyo/query */ 2005 + head->poll = tomoyo_poll_query; 2006 + head->write = tomoyo_write_answer; 2007 + head->read = tomoyo_read_query; 2008 + break; 1834 2009 case TOMOYO_MANAGER: 1835 2010 /* /sys/kernel/security/tomoyo/manager */ 1836 - head->write = tomoyo_write_manager_policy; 1837 - head->read = tomoyo_read_manager_policy; 2011 + head->write = tomoyo_write_manager; 2012 + head->read = tomoyo_read_manager; 1838 2013 break; 1839 2014 } 1840 2015 if (!(file->f_mode & FMODE_READ)) { ··· 1848 2013 * for reading. 1849 2014 */ 1850 2015 head->read = NULL; 1851 - } else { 2016 + head->poll = NULL; 2017 + } else if (!head->poll) { 2018 + /* Don't allocate read_buf for poll() access. */ 1852 2019 if (!head->readbuf_size) 1853 2020 head->readbuf_size = 4096 * 2; 1854 2021 head->read_buf = kzalloc(head->readbuf_size, GFP_NOFS); ··· 1874 2037 return -ENOMEM; 1875 2038 } 1876 2039 } 1877 - head->reader_idx = tomoyo_read_lock(); 2040 + if (type != TOMOYO_QUERY) 2041 + head->reader_idx = tomoyo_read_lock(); 1878 2042 file->private_data = head; 1879 2043 /* 1880 2044 * Call the handler now if the file is ··· 1886 2048 */ 1887 2049 if (type == TOMOYO_SELFDOMAIN) 1888 2050 tomoyo_read_control(file, NULL, 0); 2051 + /* 2052 + * If the file is /sys/kernel/security/tomoyo/query , increment the 2053 + * observer counter. 2054 + * The obserber counter is used by tomoyo_supervisor() to see if 2055 + * there is some process monitoring /sys/kernel/security/tomoyo/query. 2056 + */ 2057 + else if (type == TOMOYO_QUERY) 2058 + atomic_inc(&tomoyo_query_observers); 1889 2059 return 0; 2060 + } 2061 + 2062 + /** 2063 + * tomoyo_poll_control - poll() for /sys/kernel/security/tomoyo/ interface. 2064 + * 2065 + * @file: Pointer to "struct file". 2066 + * @wait: Pointer to "poll_table". 2067 + * 2068 + * Waits for read readiness. 2069 + * /sys/kernel/security/tomoyo/query is handled by /usr/sbin/tomoyo-queryd . 2070 + */ 2071 + int tomoyo_poll_control(struct file *file, poll_table *wait) 2072 + { 2073 + struct tomoyo_io_buffer *head = file->private_data; 2074 + if (!head->poll) 2075 + return -ENOSYS; 2076 + return head->poll(file, wait); 1890 2077 } 1891 2078 1892 2079 /** ··· 1925 2062 * 1926 2063 * Caller holds tomoyo_read_lock(). 1927 2064 */ 1928 - static int tomoyo_read_control(struct file *file, char __user *buffer, 1929 - const int buffer_len) 2065 + int tomoyo_read_control(struct file *file, char __user *buffer, 2066 + const int buffer_len) 1930 2067 { 1931 - int len = 0; 2068 + int len; 1932 2069 struct tomoyo_io_buffer *head = file->private_data; 1933 - char *cp; 1934 2070 1935 2071 if (!head->read) 1936 2072 return -ENOSYS; 1937 2073 if (mutex_lock_interruptible(&head->io_sem)) 1938 2074 return -EINTR; 1939 - /* Call the policy handler. */ 1940 - len = head->read(head); 1941 - if (len < 0) 1942 - goto out; 1943 - /* Write to buffer. */ 1944 - len = head->read_avail; 1945 - if (len > buffer_len) 1946 - len = buffer_len; 1947 - if (!len) 1948 - goto out; 1949 - /* head->read_buf changes by some functions. */ 1950 - cp = head->read_buf; 1951 - if (copy_to_user(buffer, cp, len)) { 1952 - len = -EFAULT; 1953 - goto out; 1954 - } 1955 - head->read_avail -= len; 1956 - memmove(cp, cp + len, head->read_avail); 1957 - out: 2075 + head->read_user_buf = buffer; 2076 + head->read_user_buf_avail = buffer_len; 2077 + if (tomoyo_flush(head)) 2078 + /* Call the policy handler. */ 2079 + head->read(head); 2080 + tomoyo_flush(head); 2081 + len = head->read_user_buf - buffer; 1958 2082 mutex_unlock(&head->io_sem); 1959 2083 return len; 1960 2084 } ··· 1957 2107 * 1958 2108 * Caller holds tomoyo_read_lock(). 1959 2109 */ 1960 - static int tomoyo_write_control(struct file *file, const char __user *buffer, 1961 - const int buffer_len) 2110 + int tomoyo_write_control(struct file *file, const char __user *buffer, 2111 + const int buffer_len) 1962 2112 { 1963 2113 struct tomoyo_io_buffer *head = file->private_data; 1964 2114 int error = buffer_len; ··· 1971 2121 return -EFAULT; 1972 2122 /* Don't allow updating policies by non manager programs. */ 1973 2123 if (head->write != tomoyo_write_pid && 1974 - head->write != tomoyo_write_domain_policy && 1975 - !tomoyo_is_policy_manager()) 2124 + head->write != tomoyo_write_domain && !tomoyo_manager()) 1976 2125 return -EPERM; 1977 2126 if (mutex_lock_interruptible(&head->io_sem)) 1978 2127 return -EINTR; ··· 2008 2159 * 2009 2160 * Caller looses tomoyo_read_lock(). 2010 2161 */ 2011 - static int tomoyo_close_control(struct file *file) 2162 + int tomoyo_close_control(struct file *file) 2012 2163 { 2013 2164 struct tomoyo_io_buffer *head = file->private_data; 2014 2165 const bool is_write = !!head->write_buf; 2015 2166 2016 - tomoyo_read_unlock(head->reader_idx); 2167 + /* 2168 + * If the file is /sys/kernel/security/tomoyo/query , decrement the 2169 + * observer counter. 2170 + */ 2171 + if (head->type == TOMOYO_QUERY) 2172 + atomic_dec(&tomoyo_query_observers); 2173 + else 2174 + tomoyo_read_unlock(head->reader_idx); 2017 2175 /* Release memory used for policy I/O. */ 2018 2176 kfree(head->read_buf); 2019 2177 head->read_buf = NULL; ··· 2035 2179 } 2036 2180 2037 2181 /** 2038 - * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface. 2039 - * 2040 - * @inode: Pointer to "struct inode". 2041 - * @file: Pointer to "struct file". 2042 - * 2043 - * Returns 0 on success, negative value otherwise. 2182 + * tomoyo_check_profile - Check all profiles currently assigned to domains are defined. 2044 2183 */ 2045 - static int tomoyo_open(struct inode *inode, struct file *file) 2184 + void tomoyo_check_profile(void) 2046 2185 { 2047 - const int key = ((u8 *) file->f_path.dentry->d_inode->i_private) 2048 - - ((u8 *) NULL); 2049 - return tomoyo_open_control(key, file); 2186 + struct tomoyo_domain_info *domain; 2187 + const int idx = tomoyo_read_lock(); 2188 + tomoyo_policy_loaded = true; 2189 + /* Check all profiles currently assigned to domains are defined. */ 2190 + list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { 2191 + const u8 profile = domain->profile; 2192 + if (tomoyo_profile_ptr[profile]) 2193 + continue; 2194 + panic("Profile %u (used by '%s') not defined.\n", 2195 + profile, domain->domainname->name); 2196 + } 2197 + tomoyo_read_unlock(idx); 2198 + if (tomoyo_profile_version != 20090903) 2199 + panic("Profile version %u is not supported.\n", 2200 + tomoyo_profile_version); 2201 + printk(KERN_INFO "TOMOYO: 2.3.0\n"); 2202 + printk(KERN_INFO "Mandatory Access Control activated.\n"); 2050 2203 } 2051 - 2052 - /** 2053 - * tomoyo_release - close() for /sys/kernel/security/tomoyo/ interface. 2054 - * 2055 - * @inode: Pointer to "struct inode". 2056 - * @file: Pointer to "struct file". 2057 - * 2058 - * Returns 0 on success, negative value otherwise. 2059 - */ 2060 - static int tomoyo_release(struct inode *inode, struct file *file) 2061 - { 2062 - return tomoyo_close_control(file); 2063 - } 2064 - 2065 - /** 2066 - * tomoyo_read - read() for /sys/kernel/security/tomoyo/ interface. 2067 - * 2068 - * @file: Pointer to "struct file". 2069 - * @buf: Pointer to buffer. 2070 - * @count: Size of @buf. 2071 - * @ppos: Unused. 2072 - * 2073 - * Returns bytes read on success, negative value otherwise. 2074 - */ 2075 - static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count, 2076 - loff_t *ppos) 2077 - { 2078 - return tomoyo_read_control(file, buf, count); 2079 - } 2080 - 2081 - /** 2082 - * tomoyo_write - write() for /sys/kernel/security/tomoyo/ interface. 2083 - * 2084 - * @file: Pointer to "struct file". 2085 - * @buf: Pointer to buffer. 2086 - * @count: Size of @buf. 2087 - * @ppos: Unused. 2088 - * 2089 - * Returns @count on success, negative value otherwise. 2090 - */ 2091 - static ssize_t tomoyo_write(struct file *file, const char __user *buf, 2092 - size_t count, loff_t *ppos) 2093 - { 2094 - return tomoyo_write_control(file, buf, count); 2095 - } 2096 - 2097 - /* 2098 - * tomoyo_operations is a "struct file_operations" which is used for handling 2099 - * /sys/kernel/security/tomoyo/ interface. 2100 - * 2101 - * Some files under /sys/kernel/security/tomoyo/ directory accept open(O_RDWR). 2102 - * See tomoyo_io_buffer for internals. 2103 - */ 2104 - static const struct file_operations tomoyo_operations = { 2105 - .open = tomoyo_open, 2106 - .release = tomoyo_release, 2107 - .read = tomoyo_read, 2108 - .write = tomoyo_write, 2109 - }; 2110 - 2111 - /** 2112 - * tomoyo_create_entry - Create interface files under /sys/kernel/security/tomoyo/ directory. 2113 - * 2114 - * @name: The name of the interface file. 2115 - * @mode: The permission of the interface file. 2116 - * @parent: The parent directory. 2117 - * @key: Type of interface. 2118 - * 2119 - * Returns nothing. 2120 - */ 2121 - static void __init tomoyo_create_entry(const char *name, const mode_t mode, 2122 - struct dentry *parent, const u8 key) 2123 - { 2124 - securityfs_create_file(name, mode, parent, ((u8 *) NULL) + key, 2125 - &tomoyo_operations); 2126 - } 2127 - 2128 - /** 2129 - * tomoyo_initerface_init - Initialize /sys/kernel/security/tomoyo/ interface. 2130 - * 2131 - * Returns 0. 2132 - */ 2133 - static int __init tomoyo_initerface_init(void) 2134 - { 2135 - struct dentry *tomoyo_dir; 2136 - 2137 - /* Don't create securityfs entries unless registered. */ 2138 - if (current_cred()->security != &tomoyo_kernel_domain) 2139 - return 0; 2140 - 2141 - tomoyo_dir = securityfs_create_dir("tomoyo", NULL); 2142 - tomoyo_create_entry("domain_policy", 0600, tomoyo_dir, 2143 - TOMOYO_DOMAINPOLICY); 2144 - tomoyo_create_entry("exception_policy", 0600, tomoyo_dir, 2145 - TOMOYO_EXCEPTIONPOLICY); 2146 - tomoyo_create_entry("self_domain", 0400, tomoyo_dir, 2147 - TOMOYO_SELFDOMAIN); 2148 - tomoyo_create_entry(".domain_status", 0600, tomoyo_dir, 2149 - TOMOYO_DOMAIN_STATUS); 2150 - tomoyo_create_entry(".process_status", 0600, tomoyo_dir, 2151 - TOMOYO_PROCESS_STATUS); 2152 - tomoyo_create_entry("meminfo", 0600, tomoyo_dir, 2153 - TOMOYO_MEMINFO); 2154 - tomoyo_create_entry("profile", 0600, tomoyo_dir, 2155 - TOMOYO_PROFILE); 2156 - tomoyo_create_entry("manager", 0600, tomoyo_dir, 2157 - TOMOYO_MANAGER); 2158 - tomoyo_create_entry("version", 0400, tomoyo_dir, 2159 - TOMOYO_VERSION); 2160 - return 0; 2161 - } 2162 - 2163 - fs_initcall(tomoyo_initerface_init);
+506 -346
security/tomoyo/common.h
··· 20 20 #include <linux/mount.h> 21 21 #include <linux/list.h> 22 22 #include <linux/cred.h> 23 + #include <linux/poll.h> 23 24 struct linux_binprm; 24 25 25 26 /********** Constants definitions. **********/ ··· 33 32 #define TOMOYO_HASH_BITS 8 34 33 #define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS) 35 34 36 - /* 37 - * This is the max length of a token. 38 - * 39 - * A token consists of only ASCII printable characters. 40 - * Non printable characters in a token is represented in \ooo style 41 - * octal string. Thus, \ itself is represented as \\. 42 - */ 43 - #define TOMOYO_MAX_PATHNAME_LEN 4000 35 + #define TOMOYO_EXEC_TMPSIZE 4096 44 36 45 37 /* Profile number is an integer between 0 and 255. */ 46 38 #define TOMOYO_MAX_PROFILES 256 47 39 40 + enum tomoyo_mode_index { 41 + TOMOYO_CONFIG_DISABLED, 42 + TOMOYO_CONFIG_LEARNING, 43 + TOMOYO_CONFIG_PERMISSIVE, 44 + TOMOYO_CONFIG_ENFORCING, 45 + TOMOYO_CONFIG_USE_DEFAULT = 255 46 + }; 47 + 48 + enum tomoyo_policy_id { 49 + TOMOYO_ID_GROUP, 50 + TOMOYO_ID_PATH_GROUP, 51 + TOMOYO_ID_NUMBER_GROUP, 52 + TOMOYO_ID_TRANSITION_CONTROL, 53 + TOMOYO_ID_AGGREGATOR, 54 + TOMOYO_ID_GLOBALLY_READABLE, 55 + TOMOYO_ID_PATTERN, 56 + TOMOYO_ID_NO_REWRITE, 57 + TOMOYO_ID_MANAGER, 58 + TOMOYO_ID_NAME, 59 + TOMOYO_ID_ACL, 60 + TOMOYO_ID_DOMAIN, 61 + TOMOYO_MAX_POLICY 62 + }; 63 + 64 + enum tomoyo_group_id { 65 + TOMOYO_PATH_GROUP, 66 + TOMOYO_NUMBER_GROUP, 67 + TOMOYO_MAX_GROUP 68 + }; 69 + 48 70 /* Keywords for ACLs. */ 49 - #define TOMOYO_KEYWORD_ALIAS "alias " 71 + #define TOMOYO_KEYWORD_AGGREGATOR "aggregator " 72 + #define TOMOYO_KEYWORD_ALLOW_MOUNT "allow_mount " 50 73 #define TOMOYO_KEYWORD_ALLOW_READ "allow_read " 51 74 #define TOMOYO_KEYWORD_DELETE "delete " 52 75 #define TOMOYO_KEYWORD_DENY_REWRITE "deny_rewrite " ··· 80 55 #define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain " 81 56 #define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain " 82 57 #define TOMOYO_KEYWORD_PATH_GROUP "path_group " 58 + #define TOMOYO_KEYWORD_NUMBER_GROUP "number_group " 83 59 #define TOMOYO_KEYWORD_SELECT "select " 84 60 #define TOMOYO_KEYWORD_USE_PROFILE "use_profile " 85 61 #define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read" 62 + #define TOMOYO_KEYWORD_QUOTA_EXCEEDED "quota_exceeded" 63 + #define TOMOYO_KEYWORD_TRANSITION_FAILED "transition_failed" 86 64 /* A domain definition starts with <kernel>. */ 87 65 #define TOMOYO_ROOT_NAME "<kernel>" 88 66 #define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1) 89 67 90 - /* Index numbers for Access Controls. */ 91 - enum tomoyo_mac_index { 92 - TOMOYO_MAC_FOR_FILE, /* domain_policy.conf */ 93 - TOMOYO_MAX_ACCEPT_ENTRY, 94 - TOMOYO_VERBOSE, 95 - TOMOYO_MAX_CONTROL_INDEX 68 + /* Value type definition. */ 69 + #define TOMOYO_VALUE_TYPE_INVALID 0 70 + #define TOMOYO_VALUE_TYPE_DECIMAL 1 71 + #define TOMOYO_VALUE_TYPE_OCTAL 2 72 + #define TOMOYO_VALUE_TYPE_HEXADECIMAL 3 73 + 74 + enum tomoyo_transition_type { 75 + /* Do not change this order, */ 76 + TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE, 77 + TOMOYO_TRANSITION_CONTROL_INITIALIZE, 78 + TOMOYO_TRANSITION_CONTROL_NO_KEEP, 79 + TOMOYO_TRANSITION_CONTROL_KEEP, 80 + TOMOYO_MAX_TRANSITION_TYPE 96 81 }; 97 82 98 83 /* Index numbers for Access Controls. */ 99 84 enum tomoyo_acl_entry_type_index { 100 85 TOMOYO_TYPE_PATH_ACL, 101 86 TOMOYO_TYPE_PATH2_ACL, 87 + TOMOYO_TYPE_PATH_NUMBER_ACL, 88 + TOMOYO_TYPE_MKDEV_ACL, 89 + TOMOYO_TYPE_MOUNT_ACL, 102 90 }; 103 91 104 92 /* Index numbers for File Controls. */ 105 93 106 94 /* 107 - * TYPE_READ_WRITE_ACL is special. TYPE_READ_WRITE_ACL is automatically set 108 - * if both TYPE_READ_ACL and TYPE_WRITE_ACL are set. Both TYPE_READ_ACL and 109 - * TYPE_WRITE_ACL are automatically set if TYPE_READ_WRITE_ACL is set. 110 - * TYPE_READ_WRITE_ACL is automatically cleared if either TYPE_READ_ACL or 111 - * TYPE_WRITE_ACL is cleared. Both TYPE_READ_ACL and TYPE_WRITE_ACL are 112 - * automatically cleared if TYPE_READ_WRITE_ACL is cleared. 95 + * TOMOYO_TYPE_READ_WRITE is special. TOMOYO_TYPE_READ_WRITE is automatically 96 + * set if both TOMOYO_TYPE_READ and TOMOYO_TYPE_WRITE are set. 97 + * Both TOMOYO_TYPE_READ and TOMOYO_TYPE_WRITE are automatically set if 98 + * TOMOYO_TYPE_READ_WRITE is set. 99 + * TOMOYO_TYPE_READ_WRITE is automatically cleared if either TOMOYO_TYPE_READ 100 + * or TOMOYO_TYPE_WRITE is cleared. 101 + * Both TOMOYO_TYPE_READ and TOMOYO_TYPE_WRITE are automatically cleared if 102 + * TOMOYO_TYPE_READ_WRITE is cleared. 113 103 */ 114 104 115 105 enum tomoyo_path_acl_index { ··· 132 92 TOMOYO_TYPE_EXECUTE, 133 93 TOMOYO_TYPE_READ, 134 94 TOMOYO_TYPE_WRITE, 135 - TOMOYO_TYPE_CREATE, 136 95 TOMOYO_TYPE_UNLINK, 137 - TOMOYO_TYPE_MKDIR, 138 96 TOMOYO_TYPE_RMDIR, 139 - TOMOYO_TYPE_MKFIFO, 140 - TOMOYO_TYPE_MKSOCK, 141 - TOMOYO_TYPE_MKBLOCK, 142 - TOMOYO_TYPE_MKCHAR, 143 97 TOMOYO_TYPE_TRUNCATE, 144 98 TOMOYO_TYPE_SYMLINK, 145 99 TOMOYO_TYPE_REWRITE, 146 - TOMOYO_TYPE_IOCTL, 147 - TOMOYO_TYPE_CHMOD, 148 - TOMOYO_TYPE_CHOWN, 149 - TOMOYO_TYPE_CHGRP, 150 100 TOMOYO_TYPE_CHROOT, 151 - TOMOYO_TYPE_MOUNT, 152 101 TOMOYO_TYPE_UMOUNT, 153 102 TOMOYO_MAX_PATH_OPERATION 103 + }; 104 + 105 + #define TOMOYO_RW_MASK ((1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE)) 106 + 107 + enum tomoyo_mkdev_acl_index { 108 + TOMOYO_TYPE_MKBLOCK, 109 + TOMOYO_TYPE_MKCHAR, 110 + TOMOYO_MAX_MKDEV_OPERATION 154 111 }; 155 112 156 113 enum tomoyo_path2_acl_index { ··· 155 118 TOMOYO_TYPE_RENAME, 156 119 TOMOYO_TYPE_PIVOT_ROOT, 157 120 TOMOYO_MAX_PATH2_OPERATION 121 + }; 122 + 123 + enum tomoyo_path_number_acl_index { 124 + TOMOYO_TYPE_CREATE, 125 + TOMOYO_TYPE_MKDIR, 126 + TOMOYO_TYPE_MKFIFO, 127 + TOMOYO_TYPE_MKSOCK, 128 + TOMOYO_TYPE_IOCTL, 129 + TOMOYO_TYPE_CHMOD, 130 + TOMOYO_TYPE_CHOWN, 131 + TOMOYO_TYPE_CHGRP, 132 + TOMOYO_MAX_PATH_NUMBER_OPERATION 158 133 }; 159 134 160 135 enum tomoyo_securityfs_interface_index { ··· 178 129 TOMOYO_SELFDOMAIN, 179 130 TOMOYO_VERSION, 180 131 TOMOYO_PROFILE, 132 + TOMOYO_QUERY, 181 133 TOMOYO_MANAGER 182 134 }; 135 + 136 + enum tomoyo_mac_index { 137 + TOMOYO_MAC_FILE_EXECUTE, 138 + TOMOYO_MAC_FILE_OPEN, 139 + TOMOYO_MAC_FILE_CREATE, 140 + TOMOYO_MAC_FILE_UNLINK, 141 + TOMOYO_MAC_FILE_MKDIR, 142 + TOMOYO_MAC_FILE_RMDIR, 143 + TOMOYO_MAC_FILE_MKFIFO, 144 + TOMOYO_MAC_FILE_MKSOCK, 145 + TOMOYO_MAC_FILE_TRUNCATE, 146 + TOMOYO_MAC_FILE_SYMLINK, 147 + TOMOYO_MAC_FILE_REWRITE, 148 + TOMOYO_MAC_FILE_MKBLOCK, 149 + TOMOYO_MAC_FILE_MKCHAR, 150 + TOMOYO_MAC_FILE_LINK, 151 + TOMOYO_MAC_FILE_RENAME, 152 + TOMOYO_MAC_FILE_CHMOD, 153 + TOMOYO_MAC_FILE_CHOWN, 154 + TOMOYO_MAC_FILE_CHGRP, 155 + TOMOYO_MAC_FILE_IOCTL, 156 + TOMOYO_MAC_FILE_CHROOT, 157 + TOMOYO_MAC_FILE_MOUNT, 158 + TOMOYO_MAC_FILE_UMOUNT, 159 + TOMOYO_MAC_FILE_PIVOT_ROOT, 160 + TOMOYO_MAX_MAC_INDEX 161 + }; 162 + 163 + enum tomoyo_mac_category_index { 164 + TOMOYO_MAC_CATEGORY_FILE, 165 + TOMOYO_MAX_MAC_CATEGORY_INDEX 166 + }; 167 + 168 + #define TOMOYO_RETRY_REQUEST 1 /* Retry this request. */ 183 169 184 170 /********** Structure definitions. **********/ 185 171 186 172 /* 187 - * tomoyo_page_buffer is a structure which is used for holding a pathname 188 - * obtained from "struct dentry" and "struct vfsmount" pair. 189 - * As of now, it is 4096 bytes. If users complain that 4096 bytes is too small 190 - * (because TOMOYO escapes non ASCII printable characters using \ooo format), 191 - * we will make the buffer larger. 173 + * tomoyo_acl_head is a structure which is used for holding elements not in 174 + * domain policy. 175 + * It has following fields. 176 + * 177 + * (1) "list" which is linked to tomoyo_policy_list[] . 178 + * (2) "is_deleted" is a bool which is true if marked as deleted, false 179 + * otherwise. 192 180 */ 193 - struct tomoyo_page_buffer { 194 - char buffer[4096]; 181 + struct tomoyo_acl_head { 182 + struct list_head list; 183 + bool is_deleted; 184 + } __packed; 185 + 186 + /* 187 + * tomoyo_request_info is a structure which is used for holding 188 + * 189 + * (1) Domain information of current process. 190 + * (2) How many retries are made for this request. 191 + * (3) Profile number used for this request. 192 + * (4) Access control mode of the profile. 193 + */ 194 + struct tomoyo_request_info { 195 + struct tomoyo_domain_info *domain; 196 + /* For holding parameters. */ 197 + union { 198 + struct { 199 + const struct tomoyo_path_info *filename; 200 + /* For using wildcards at tomoyo_find_next_domain(). */ 201 + const struct tomoyo_path_info *matched_path; 202 + u8 operation; 203 + } path; 204 + struct { 205 + const struct tomoyo_path_info *filename1; 206 + const struct tomoyo_path_info *filename2; 207 + u8 operation; 208 + } path2; 209 + struct { 210 + const struct tomoyo_path_info *filename; 211 + unsigned int mode; 212 + unsigned int major; 213 + unsigned int minor; 214 + u8 operation; 215 + } mkdev; 216 + struct { 217 + const struct tomoyo_path_info *filename; 218 + unsigned long number; 219 + u8 operation; 220 + } path_number; 221 + struct { 222 + const struct tomoyo_path_info *type; 223 + const struct tomoyo_path_info *dir; 224 + const struct tomoyo_path_info *dev; 225 + unsigned long flags; 226 + int need_dev; 227 + } mount; 228 + } param; 229 + u8 param_type; 230 + bool granted; 231 + u8 retry; 232 + u8 profile; 233 + u8 mode; /* One of tomoyo_mode_index . */ 234 + u8 type; 195 235 }; 196 236 197 237 /* ··· 312 174 }; 313 175 314 176 /* 315 - * tomoyo_name_entry is a structure which is used for linking 177 + * tomoyo_name is a structure which is used for linking 316 178 * "struct tomoyo_path_info" into tomoyo_name_list . 317 179 */ 318 - struct tomoyo_name_entry { 180 + struct tomoyo_name { 319 181 struct list_head list; 320 182 atomic_t users; 321 183 struct tomoyo_path_info entry; 322 184 }; 323 185 324 - /* 325 - * tomoyo_path_info_with_data is a structure which is used for holding a 326 - * pathname obtained from "struct dentry" and "struct vfsmount" pair. 327 - * 328 - * "struct tomoyo_path_info_with_data" consists of "struct tomoyo_path_info" 329 - * and buffer for the pathname, while "struct tomoyo_page_buffer" consists of 330 - * buffer for the pathname only. 331 - * 332 - * "struct tomoyo_path_info_with_data" is intended to allow TOMOYO to release 333 - * both "struct tomoyo_path_info" and buffer for the pathname by single kfree() 334 - * so that we don't need to return two pointers to the caller. If the caller 335 - * puts "struct tomoyo_path_info" on stack memory, we will be able to remove 336 - * "struct tomoyo_path_info_with_data". 337 - */ 338 - struct tomoyo_path_info_with_data { 339 - /* Keep "head" first, for this pointer is passed to kfree(). */ 340 - struct tomoyo_path_info head; 341 - char barrier1[16]; /* Safeguard for overrun. */ 342 - char body[TOMOYO_MAX_PATHNAME_LEN]; 343 - char barrier2[16]; /* Safeguard for overrun. */ 344 - }; 345 - 346 186 struct tomoyo_name_union { 347 187 const struct tomoyo_path_info *filename; 348 - struct tomoyo_path_group *group; 188 + struct tomoyo_group *group; 349 189 u8 is_group; 350 190 }; 351 191 352 - /* Structure for "path_group" directive. */ 353 - struct tomoyo_path_group { 192 + struct tomoyo_number_union { 193 + unsigned long values[2]; 194 + struct tomoyo_group *group; 195 + u8 min_type; 196 + u8 max_type; 197 + u8 is_group; 198 + }; 199 + 200 + /* Structure for "path_group"/"number_group" directive. */ 201 + struct tomoyo_group { 354 202 struct list_head list; 355 203 const struct tomoyo_path_info *group_name; 356 204 struct list_head member_list; ··· 344 220 }; 345 221 346 222 /* Structure for "path_group" directive. */ 347 - struct tomoyo_path_group_member { 348 - struct list_head list; 349 - bool is_deleted; 223 + struct tomoyo_path_group { 224 + struct tomoyo_acl_head head; 350 225 const struct tomoyo_path_info *member_name; 226 + }; 227 + 228 + /* Structure for "number_group" directive. */ 229 + struct tomoyo_number_group { 230 + struct tomoyo_acl_head head; 231 + struct tomoyo_number_union number; 351 232 }; 352 233 353 234 /* ··· 360 231 * 361 232 * (1) "list" which is linked to the ->acl_info_list of 362 233 * "struct tomoyo_domain_info" 363 - * (2) "type" which tells type of the entry (either 364 - * "struct tomoyo_path_acl" or "struct tomoyo_path2_acl"). 234 + * (2) "is_deleted" is a bool which is true if this domain is marked as 235 + * "deleted", false otherwise. 236 + * (3) "type" which tells type of the entry. 365 237 * 366 238 * Packing "struct tomoyo_acl_info" allows 367 - * "struct tomoyo_path_acl" to embed "u8" + "u16" and 368 - * "struct tomoyo_path2_acl" to embed "u8" 369 - * without enlarging their structure size. 239 + * "struct tomoyo_path_acl" to embed "u16" and "struct tomoyo_path2_acl" 240 + * "struct tomoyo_path_number_acl" "struct tomoyo_mkdev_acl" to embed 241 + * "u8" without enlarging their structure size. 370 242 */ 371 243 struct tomoyo_acl_info { 372 244 struct list_head list; 373 - u8 type; 245 + bool is_deleted; 246 + u8 type; /* = one of values in "enum tomoyo_acl_entry_type_index". */ 374 247 } __packed; 375 248 376 249 /* ··· 430 299 * (3) "name" is the pathname. 431 300 * 432 301 * Directives held by this structure are "allow_read/write", "allow_execute", 433 - * "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir", 434 - * "allow_rmdir", "allow_mkfifo", "allow_mksock", "allow_mkblock", 435 - * "allow_mkchar", "allow_truncate", "allow_symlink", "allow_rewrite", 436 - * "allow_chmod", "allow_chown", "allow_chgrp", "allow_chroot", "allow_mount" 437 - * and "allow_unmount". 302 + * "allow_read", "allow_write", "allow_unlink", "allow_rmdir", 303 + * "allow_truncate", "allow_symlink", "allow_rewrite", "allow_chroot" and 304 + * "allow_unmount". 438 305 */ 439 306 struct tomoyo_path_acl { 440 307 struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ 441 - u8 perm_high; 442 308 u16 perm; 443 309 struct tomoyo_name_union name; 310 + }; 311 + 312 + /* 313 + * tomoyo_path_number_acl is a structure which is used for holding an 314 + * entry with one pathname and one number operation. 315 + * It has following fields. 316 + * 317 + * (1) "head" which is a "struct tomoyo_acl_info". 318 + * (2) "perm" which is a bitmask of permitted operations. 319 + * (3) "name" is the pathname. 320 + * (4) "number" is the numeric value. 321 + * 322 + * Directives held by this structure are "allow_create", "allow_mkdir", 323 + * "allow_ioctl", "allow_mkfifo", "allow_mksock", "allow_chmod", "allow_chown" 324 + * and "allow_chgrp". 325 + * 326 + */ 327 + struct tomoyo_path_number_acl { 328 + struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_NUMBER_ACL */ 329 + u8 perm; 330 + struct tomoyo_name_union name; 331 + struct tomoyo_number_union number; 332 + }; 333 + 334 + /* 335 + * tomoyo_mkdev_acl is a structure which is used for holding an 336 + * entry with one pathname and three numbers operation. 337 + * It has following fields. 338 + * 339 + * (1) "head" which is a "struct tomoyo_acl_info". 340 + * (2) "perm" which is a bitmask of permitted operations. 341 + * (3) "mode" is the create mode. 342 + * (4) "major" is the major number of device node. 343 + * (5) "minor" is the minor number of device node. 344 + * 345 + * Directives held by this structure are "allow_mkchar", "allow_mkblock". 346 + * 347 + */ 348 + struct tomoyo_mkdev_acl { 349 + struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MKDEV_ACL */ 350 + u8 perm; 351 + struct tomoyo_name_union name; 352 + struct tomoyo_number_union mode; 353 + struct tomoyo_number_union major; 354 + struct tomoyo_number_union minor; 444 355 }; 445 356 446 357 /* ··· 506 333 }; 507 334 508 335 /* 509 - * tomoyo_io_buffer is a structure which is used for reading and modifying 510 - * configuration via /sys/kernel/security/tomoyo/ interface. 511 - * It has many fields. ->read_var1 , ->read_var2 , ->write_var1 are used as 512 - * cursors. 336 + * tomoyo_mount_acl is a structure which is used for holding an 337 + * entry for mount operation. 338 + * It has following fields. 513 339 * 514 - * Since the content of /sys/kernel/security/tomoyo/domain_policy is a list of 515 - * "struct tomoyo_domain_info" entries and each "struct tomoyo_domain_info" 516 - * entry has a list of "struct tomoyo_acl_info", we need two cursors when 517 - * reading (one is for traversing tomoyo_domain_list and the other is for 518 - * traversing "struct tomoyo_acl_info"->acl_info_list ). 340 + * (1) "head" which is a "struct tomoyo_acl_info". 341 + * (2) "dev_name" is the device name. 342 + * (3) "dir_name" is the mount point. 343 + * (4) "fs_type" is the filesystem type. 344 + * (5) "flags" is the mount flags. 519 345 * 520 - * If a line written to /sys/kernel/security/tomoyo/domain_policy starts with 521 - * "select ", TOMOYO seeks the cursor ->read_var1 and ->write_var1 to the 522 - * domain with the domainname specified by the rest of that line (NULL is set 523 - * if seek failed). 524 - * If a line written to /sys/kernel/security/tomoyo/domain_policy starts with 525 - * "delete ", TOMOYO deletes an entry or a domain specified by the rest of that 526 - * line (->write_var1 is set to NULL if a domain was deleted). 527 - * If a line written to /sys/kernel/security/tomoyo/domain_policy starts with 528 - * neither "select " nor "delete ", an entry or a domain specified by that line 529 - * is appended. 346 + * Directive held by this structure is "allow_mount". 347 + */ 348 + struct tomoyo_mount_acl { 349 + struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MOUNT_ACL */ 350 + struct tomoyo_name_union dev_name; 351 + struct tomoyo_name_union dir_name; 352 + struct tomoyo_name_union fs_type; 353 + struct tomoyo_number_union flags; 354 + }; 355 + 356 + #define TOMOYO_MAX_IO_READ_QUEUE 32 357 + 358 + /* 359 + * Structure for reading/writing policy via /sys/kernel/security/tomoyo 360 + * interfaces. 530 361 */ 531 362 struct tomoyo_io_buffer { 532 - int (*read) (struct tomoyo_io_buffer *); 363 + void (*read) (struct tomoyo_io_buffer *); 533 364 int (*write) (struct tomoyo_io_buffer *); 365 + int (*poll) (struct file *file, poll_table *wait); 534 366 /* Exclusive lock for this structure. */ 535 367 struct mutex io_sem; 536 368 /* Index returned by tomoyo_read_lock(). */ 537 369 int reader_idx; 538 - /* The position currently reading from. */ 539 - struct list_head *read_var1; 540 - /* Extra variables for reading. */ 541 - struct list_head *read_var2; 370 + char __user *read_user_buf; 371 + int read_user_buf_avail; 372 + struct { 373 + struct list_head *domain; 374 + struct list_head *group; 375 + struct list_head *acl; 376 + int avail; 377 + int step; 378 + int query_index; 379 + u16 index; 380 + u8 bit; 381 + u8 w_pos; 382 + bool eof; 383 + bool print_this_domain_only; 384 + bool print_execute_only; 385 + const char *w[TOMOYO_MAX_IO_READ_QUEUE]; 386 + } r; 542 387 /* The position currently writing to. */ 543 388 struct tomoyo_domain_info *write_var1; 544 - /* The step for reading. */ 545 - int read_step; 546 389 /* Buffer for reading. */ 547 390 char *read_buf; 548 - /* EOF flag for reading. */ 549 - bool read_eof; 550 - /* Read domain ACL of specified PID? */ 551 - bool read_single_domain; 552 - /* Extra variable for reading. */ 553 - u8 read_bit; 554 - /* Bytes available for reading. */ 555 - int read_avail; 556 391 /* Size of read buffer. */ 557 392 int readbuf_size; 558 393 /* Buffer for writing. */ ··· 569 388 int write_avail; 570 389 /* Size of write buffer. */ 571 390 int writebuf_size; 391 + /* Type of this interface. */ 392 + u8 type; 572 393 }; 573 394 574 395 /* 575 - * tomoyo_globally_readable_file_entry is a structure which is used for holding 396 + * tomoyo_readable_file is a structure which is used for holding 576 397 * "allow_read" entries. 577 398 * It has following fields. 578 399 * 579 - * (1) "list" which is linked to tomoyo_globally_readable_list . 400 + * (1) "head" is "struct tomoyo_acl_head". 580 401 * (2) "filename" is a pathname which is allowed to open(O_RDONLY). 581 - * (3) "is_deleted" is a bool which is true if marked as deleted, false 582 - * otherwise. 583 402 */ 584 - struct tomoyo_globally_readable_file_entry { 585 - struct list_head list; 403 + struct tomoyo_readable_file { 404 + struct tomoyo_acl_head head; 586 405 const struct tomoyo_path_info *filename; 587 - bool is_deleted; 588 406 }; 589 407 590 408 /* 591 - * tomoyo_pattern_entry is a structure which is used for holding 592 - * "tomoyo_pattern_list" entries. 409 + * tomoyo_no_pattern is a structure which is used for holding 410 + * "file_pattern" entries. 593 411 * It has following fields. 594 412 * 595 - * (1) "list" which is linked to tomoyo_pattern_list . 413 + * (1) "head" is "struct tomoyo_acl_head". 596 414 * (2) "pattern" is a pathname pattern which is used for converting pathnames 597 415 * to pathname patterns during learning mode. 598 - * (3) "is_deleted" is a bool which is true if marked as deleted, false 599 - * otherwise. 600 416 */ 601 - struct tomoyo_pattern_entry { 602 - struct list_head list; 417 + struct tomoyo_no_pattern { 418 + struct tomoyo_acl_head head; 603 419 const struct tomoyo_path_info *pattern; 604 - bool is_deleted; 605 420 }; 606 421 607 422 /* 608 - * tomoyo_no_rewrite_entry is a structure which is used for holding 423 + * tomoyo_no_rewrite is a structure which is used for holding 609 424 * "deny_rewrite" entries. 610 425 * It has following fields. 611 426 * 612 - * (1) "list" which is linked to tomoyo_no_rewrite_list . 427 + * (1) "head" is "struct tomoyo_acl_head". 613 428 * (2) "pattern" is a pathname which is by default not permitted to modify 614 429 * already existing content. 615 - * (3) "is_deleted" is a bool which is true if marked as deleted, false 616 - * otherwise. 617 430 */ 618 - struct tomoyo_no_rewrite_entry { 619 - struct list_head list; 431 + struct tomoyo_no_rewrite { 432 + struct tomoyo_acl_head head; 620 433 const struct tomoyo_path_info *pattern; 621 - bool is_deleted; 622 434 }; 623 435 624 436 /* 625 - * tomoyo_domain_initializer_entry is a structure which is used for holding 626 - * "initialize_domain" and "no_initialize_domain" entries. 437 + * tomoyo_transition_control is a structure which is used for holding 438 + * "initialize_domain"/"no_initialize_domain"/"keep_domain"/"no_keep_domain" 439 + * entries. 627 440 * It has following fields. 628 441 * 629 - * (1) "list" which is linked to tomoyo_domain_initializer_list . 630 - * (2) "domainname" which is "a domainname" or "the last component of a 631 - * domainname". This field is NULL if "from" clause is not specified. 632 - * (3) "program" which is a program's pathname. 633 - * (4) "is_deleted" is a bool which is true if marked as deleted, false 634 - * otherwise. 635 - * (5) "is_not" is a bool which is true if "no_initialize_domain", false 636 - * otherwise. 637 - * (6) "is_last_name" is a bool which is true if "domainname" is "the last 442 + * (1) "head" is "struct tomoyo_acl_head". 443 + * (2) "type" is type of this entry. 444 + * (3) "is_last_name" is a bool which is true if "domainname" is "the last 638 445 * component of a domainname", false otherwise. 639 - */ 640 - struct tomoyo_domain_initializer_entry { 641 - struct list_head list; 642 - const struct tomoyo_path_info *domainname; /* This may be NULL */ 643 - const struct tomoyo_path_info *program; 644 - bool is_deleted; 645 - bool is_not; /* True if this entry is "no_initialize_domain". */ 646 - /* True if the domainname is tomoyo_get_last_name(). */ 647 - bool is_last_name; 648 - }; 649 - 650 - /* 651 - * tomoyo_domain_keeper_entry is a structure which is used for holding 652 - * "keep_domain" and "no_keep_domain" entries. 653 - * It has following fields. 654 - * 655 - * (1) "list" which is linked to tomoyo_domain_keeper_list . 656 - * (2) "domainname" which is "a domainname" or "the last component of a 446 + * (4) "domainname" which is "a domainname" or "the last component of a 657 447 * domainname". 658 - * (3) "program" which is a program's pathname. 659 - * This field is NULL if "from" clause is not specified. 660 - * (4) "is_deleted" is a bool which is true if marked as deleted, false 661 - * otherwise. 662 - * (5) "is_not" is a bool which is true if "no_initialize_domain", false 663 - * otherwise. 664 - * (6) "is_last_name" is a bool which is true if "domainname" is "the last 665 - * component of a domainname", false otherwise. 448 + * (5) "program" which is a program's pathname. 666 449 */ 667 - struct tomoyo_domain_keeper_entry { 668 - struct list_head list; 669 - const struct tomoyo_path_info *domainname; 670 - const struct tomoyo_path_info *program; /* This may be NULL */ 671 - bool is_deleted; 672 - bool is_not; /* True if this entry is "no_keep_domain". */ 450 + struct tomoyo_transition_control { 451 + struct tomoyo_acl_head head; 452 + u8 type; /* One of values in "enum tomoyo_transition_type". */ 673 453 /* True if the domainname is tomoyo_get_last_name(). */ 674 454 bool is_last_name; 455 + const struct tomoyo_path_info *domainname; /* Maybe NULL */ 456 + const struct tomoyo_path_info *program; /* Maybe NULL */ 675 457 }; 676 458 677 459 /* 678 - * tomoyo_alias_entry is a structure which is used for holding "alias" entries. 460 + * tomoyo_aggregator is a structure which is used for holding 461 + * "aggregator" entries. 679 462 * It has following fields. 680 463 * 681 - * (1) "list" which is linked to tomoyo_alias_list . 682 - * (2) "original_name" which is a dereferenced pathname. 683 - * (3) "aliased_name" which is a symlink's pathname. 684 - * (4) "is_deleted" is a bool which is true if marked as deleted, false 685 - * otherwise. 464 + * (1) "head" is "struct tomoyo_acl_head". 465 + * (2) "original_name" which is originally requested name. 466 + * (3) "aggregated_name" which is name to rewrite. 686 467 */ 687 - struct tomoyo_alias_entry { 688 - struct list_head list; 468 + struct tomoyo_aggregator { 469 + struct tomoyo_acl_head head; 689 470 const struct tomoyo_path_info *original_name; 690 - const struct tomoyo_path_info *aliased_name; 691 - bool is_deleted; 471 + const struct tomoyo_path_info *aggregated_name; 692 472 }; 693 473 694 474 /* 695 - * tomoyo_policy_manager_entry is a structure which is used for holding list of 475 + * tomoyo_manager is a structure which is used for holding list of 696 476 * domainnames or programs which are permitted to modify configuration via 697 477 * /sys/kernel/security/tomoyo/ interface. 698 478 * It has following fields. 699 479 * 700 - * (1) "list" which is linked to tomoyo_policy_manager_list . 701 - * (2) "manager" is a domainname or a program's pathname. 702 - * (3) "is_domain" is a bool which is true if "manager" is a domainname, false 480 + * (1) "head" is "struct tomoyo_acl_head". 481 + * (2) "is_domain" is a bool which is true if "manager" is a domainname, false 703 482 * otherwise. 704 - * (4) "is_deleted" is a bool which is true if marked as deleted, false 705 - * otherwise. 483 + * (3) "manager" is a domainname or a program's pathname. 706 484 */ 707 - struct tomoyo_policy_manager_entry { 708 - struct list_head list; 485 + struct tomoyo_manager { 486 + struct tomoyo_acl_head head; 487 + bool is_domain; /* True if manager is a domainname. */ 709 488 /* A path to program or a domainname. */ 710 489 const struct tomoyo_path_info *manager; 711 - bool is_domain; /* True if manager is a domainname. */ 712 - bool is_deleted; /* True if this entry is deleted. */ 490 + }; 491 + 492 + struct tomoyo_preference { 493 + unsigned int learning_max_entry; 494 + bool enforcing_verbose; 495 + bool learning_verbose; 496 + bool permissive_verbose; 497 + }; 498 + 499 + struct tomoyo_profile { 500 + const struct tomoyo_path_info *comment; 501 + struct tomoyo_preference *learning; 502 + struct tomoyo_preference *permissive; 503 + struct tomoyo_preference *enforcing; 504 + struct tomoyo_preference preference; 505 + u8 default_config; 506 + u8 config[TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX]; 713 507 }; 714 508 715 509 /********** Function prototypes. **********/ 716 510 717 - /* Check whether the given name matches the given name_union. */ 718 - bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, 719 - const struct tomoyo_name_union *ptr); 511 + extern asmlinkage long sys_getpid(void); 512 + extern asmlinkage long sys_getppid(void); 513 + 514 + /* Check whether the given string starts with the given keyword. */ 515 + bool tomoyo_str_starts(char **src, const char *find); 516 + /* Get tomoyo_realpath() of current process. */ 517 + const char *tomoyo_get_exe(void); 518 + /* Format string. */ 519 + void tomoyo_normalize_line(unsigned char *buffer); 520 + /* Print warning or error message on console. */ 521 + void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...) 522 + __attribute__ ((format(printf, 2, 3))); 523 + /* Check all profiles currently assigned to domains are defined. */ 524 + void tomoyo_check_profile(void); 525 + /* Open operation for /sys/kernel/security/tomoyo/ interface. */ 526 + int tomoyo_open_control(const u8 type, struct file *file); 527 + /* Close /sys/kernel/security/tomoyo/ interface. */ 528 + int tomoyo_close_control(struct file *file); 529 + /* Poll operation for /sys/kernel/security/tomoyo/ interface. */ 530 + int tomoyo_poll_control(struct file *file, poll_table *wait); 531 + /* Read operation for /sys/kernel/security/tomoyo/ interface. */ 532 + int tomoyo_read_control(struct file *file, char __user *buffer, 533 + const int buffer_len); 534 + /* Write operation for /sys/kernel/security/tomoyo/ interface. */ 535 + int tomoyo_write_control(struct file *file, const char __user *buffer, 536 + const int buffer_len); 720 537 /* Check whether the domain has too many ACL entries to hold. */ 721 - bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain); 722 - /* Transactional sprintf() for policy dump. */ 723 - bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) 538 + bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r); 539 + /* Print out of memory warning message. */ 540 + void tomoyo_warn_oom(const char *function); 541 + /* Check whether the given name matches the given name_union. */ 542 + const struct tomoyo_path_info * 543 + tomoyo_compare_name_union(const struct tomoyo_path_info *name, 544 + const struct tomoyo_name_union *ptr); 545 + /* Check whether the given number matches the given number_union. */ 546 + bool tomoyo_compare_number_union(const unsigned long value, 547 + const struct tomoyo_number_union *ptr); 548 + int tomoyo_get_mode(const u8 profile, const u8 index); 549 + void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) 724 550 __attribute__ ((format(printf, 2, 3))); 725 551 /* Check whether the domainname is correct. */ 726 - bool tomoyo_is_correct_domain(const unsigned char *domainname); 552 + bool tomoyo_correct_domain(const unsigned char *domainname); 727 553 /* Check whether the token is correct. */ 728 - bool tomoyo_is_correct_path(const char *filename, const s8 start_type, 729 - const s8 pattern_type, const s8 end_type); 554 + bool tomoyo_correct_path(const char *filename); 555 + bool tomoyo_correct_word(const char *string); 730 556 /* Check whether the token can be a domainname. */ 731 - bool tomoyo_is_domain_def(const unsigned char *buffer); 557 + bool tomoyo_domain_def(const unsigned char *buffer); 732 558 bool tomoyo_parse_name_union(const char *filename, 733 559 struct tomoyo_name_union *ptr); 734 560 /* Check whether the given filename matches the given path_group. */ 735 - bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, 736 - const struct tomoyo_path_group *group, 737 - const bool may_use_pattern); 561 + const struct tomoyo_path_info * 562 + tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, 563 + const struct tomoyo_group *group); 564 + /* Check whether the given value matches the given number_group. */ 565 + bool tomoyo_number_matches_group(const unsigned long min, 566 + const unsigned long max, 567 + const struct tomoyo_group *group); 738 568 /* Check whether the given filename matches the given pattern. */ 739 569 bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, 740 570 const struct tomoyo_path_info *pattern); 741 - /* Read "alias" entry in exception policy. */ 742 - bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head); 743 - /* 744 - * Read "initialize_domain" and "no_initialize_domain" entry 745 - * in exception policy. 746 - */ 747 - bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head); 748 - /* Read "keep_domain" and "no_keep_domain" entry in exception policy. */ 749 - bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head); 750 - /* Read "file_pattern" entry in exception policy. */ 751 - bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head); 752 - /* Read "path_group" entry in exception policy. */ 753 - bool tomoyo_read_path_group_policy(struct tomoyo_io_buffer *head); 754 - /* Read "allow_read" entry in exception policy. */ 755 - bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head); 756 - /* Read "deny_rewrite" entry in exception policy. */ 757 - bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head); 571 + 572 + bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num); 758 573 /* Tokenize a line. */ 759 574 bool tomoyo_tokenize(char *buffer, char *w[], size_t size); 760 575 /* Write domain policy violation warning message to console? */ 761 576 bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); 762 - /* Convert double path operation to operation name. */ 763 - const char *tomoyo_path22keyword(const u8 operation); 764 - /* Get the last component of the given domainname. */ 765 - const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain); 766 - /* Get warning message. */ 767 - const char *tomoyo_get_msg(const bool is_enforce); 768 - /* Convert single path operation to operation name. */ 769 - const char *tomoyo_path2keyword(const u8 operation); 770 - /* Create "alias" entry in exception policy. */ 771 - int tomoyo_write_alias_policy(char *data, const bool is_delete); 772 - /* 773 - * Create "initialize_domain" and "no_initialize_domain" entry 774 - * in exception policy. 775 - */ 776 - int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, 777 - const bool is_delete); 778 - /* Create "keep_domain" and "no_keep_domain" entry in exception policy. */ 779 - int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, 780 - const bool is_delete); 577 + /* Fill "struct tomoyo_request_info". */ 578 + int tomoyo_init_request_info(struct tomoyo_request_info *r, 579 + struct tomoyo_domain_info *domain, 580 + const u8 index); 581 + /* Check permission for mount operation. */ 582 + int tomoyo_mount_permission(char *dev_name, struct path *path, char *type, 583 + unsigned long flags, void *data_page); 584 + /* Create "aggregator" entry in exception policy. */ 585 + int tomoyo_write_aggregator(char *data, const bool is_delete); 586 + int tomoyo_write_transition_control(char *data, const bool is_delete, 587 + const u8 type); 781 588 /* 782 589 * Create "allow_read/write", "allow_execute", "allow_read", "allow_write", 783 590 * "allow_create", "allow_unlink", "allow_mkdir", "allow_rmdir", ··· 773 604 * "allow_truncate", "allow_symlink", "allow_rewrite", "allow_rename" and 774 605 * "allow_link" entry in domain policy. 775 606 */ 776 - int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, 777 - const bool is_delete); 607 + int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain, 608 + const bool is_delete); 778 609 /* Create "allow_read" entry in exception policy. */ 779 - int tomoyo_write_globally_readable_policy(char *data, const bool is_delete); 610 + int tomoyo_write_globally_readable(char *data, const bool is_delete); 611 + /* Create "allow_mount" entry in domain policy. */ 612 + int tomoyo_write_mount(char *data, struct tomoyo_domain_info *domain, 613 + const bool is_delete); 780 614 /* Create "deny_rewrite" entry in exception policy. */ 781 - int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete); 615 + int tomoyo_write_no_rewrite(char *data, const bool is_delete); 782 616 /* Create "file_pattern" entry in exception policy. */ 783 - int tomoyo_write_pattern_policy(char *data, const bool is_delete); 784 - /* Create "path_group" entry in exception policy. */ 785 - int tomoyo_write_path_group_policy(char *data, const bool is_delete); 617 + int tomoyo_write_pattern(char *data, const bool is_delete); 618 + /* Create "path_group"/"number_group" entry in exception policy. */ 619 + int tomoyo_write_group(char *data, const bool is_delete, const u8 type); 620 + int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) 621 + __attribute__ ((format(printf, 2, 3))); 786 622 /* Find a domain by the given name. */ 787 623 struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); 788 624 /* Find or create a domain by the given name. */ 789 - struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * 790 - domainname, 791 - const u8 profile); 792 - 793 - /* Allocate memory for "struct tomoyo_path_group". */ 794 - struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name); 625 + struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, 626 + const u8 profile); 627 + struct tomoyo_profile *tomoyo_profile(const u8 profile); 628 + /* 629 + * Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group". 630 + */ 631 + struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 type); 795 632 796 633 /* Check mode for specified functionality. */ 797 634 unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, ··· 807 632 /* Run policy loader when /sbin/init starts. */ 808 633 void tomoyo_load_policy(const char *filename); 809 634 635 + void tomoyo_put_number_union(struct tomoyo_number_union *ptr); 636 + 810 637 /* Convert binary string to ascii string. */ 811 - int tomoyo_encode(char *buffer, int buflen, const char *str); 812 - 813 - /* Returns realpath(3) of the given pathname but ignores chroot'ed root. */ 814 - int tomoyo_realpath_from_path2(struct path *path, char *newname, 815 - int newname_len); 638 + char *tomoyo_encode(const char *str); 816 639 817 640 /* 818 - * Returns realpath(3) of the given pathname but ignores chroot'ed root. 819 - * These functions use kzalloc(), so the caller must call kfree() 820 - * if these functions didn't return NULL. 821 - */ 822 - char *tomoyo_realpath(const char *pathname); 823 - /* 824 - * Same with tomoyo_realpath() except that it doesn't follow the final symlink. 641 + * Returns realpath(3) of the given pathname except that 642 + * ignores chroot'ed root and does not follow the final symlink. 825 643 */ 826 644 char *tomoyo_realpath_nofollow(const char *pathname); 827 - /* Same with tomoyo_realpath() except that the pathname is already solved. */ 645 + /* 646 + * Returns realpath(3) of the given pathname except that 647 + * ignores chroot'ed root and the pathname is already solved. 648 + */ 828 649 char *tomoyo_realpath_from_path(struct path *path); 650 + /* Get patterned pathname. */ 651 + const char *tomoyo_pattern(const struct tomoyo_path_info *filename); 829 652 830 653 /* Check memory quota. */ 831 654 bool tomoyo_memory_ok(void *ptr); ··· 836 663 const struct tomoyo_path_info *tomoyo_get_name(const char *name); 837 664 838 665 /* Check for memory usage. */ 839 - int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head); 666 + void tomoyo_read_memory_counter(struct tomoyo_io_buffer *head); 840 667 841 668 /* Set memory quota. */ 842 669 int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head); 843 670 844 - /* Initialize realpath related code. */ 845 - void __init tomoyo_realpath_init(void); 846 - int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, 671 + /* Initialize mm related code. */ 672 + void __init tomoyo_mm_init(void); 673 + int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, 847 674 const struct tomoyo_path_info *filename); 848 675 int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, 849 676 struct path *path, const int flag); 677 + int tomoyo_path_number_perm(const u8 operation, struct path *path, 678 + unsigned long number); 679 + int tomoyo_mkdev_perm(const u8 operation, struct path *path, 680 + const unsigned int mode, unsigned int dev); 850 681 int tomoyo_path_perm(const u8 operation, struct path *path); 851 682 int tomoyo_path2_perm(const u8 operation, struct path *path1, 852 683 struct path *path2); 853 - int tomoyo_check_rewrite_permission(struct file *filp); 854 684 int tomoyo_find_next_domain(struct linux_binprm *bprm); 685 + 686 + void tomoyo_print_ulong(char *buffer, const int buffer_len, 687 + const unsigned long value, const u8 type); 855 688 856 689 /* Drop refcount on tomoyo_name_union. */ 857 690 void tomoyo_put_name_union(struct tomoyo_name_union *ptr); ··· 867 688 868 689 void tomoyo_memory_free(void *ptr); 869 690 691 + int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, 692 + bool is_delete, struct tomoyo_domain_info *domain, 693 + bool (*check_duplicate) (const struct tomoyo_acl_info 694 + *, 695 + const struct tomoyo_acl_info 696 + *), 697 + bool (*merge_duplicate) (struct tomoyo_acl_info *, 698 + struct tomoyo_acl_info *, 699 + const bool)); 700 + int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, 701 + bool is_delete, struct list_head *list, 702 + bool (*check_duplicate) (const struct tomoyo_acl_head 703 + *, 704 + const struct tomoyo_acl_head 705 + *)); 706 + void tomoyo_check_acl(struct tomoyo_request_info *r, 707 + bool (*check_entry) (struct tomoyo_request_info *, 708 + const struct tomoyo_acl_info *)); 709 + 870 710 /********** External variable definitions. **********/ 871 711 872 712 /* Lock for GC. */ ··· 894 696 /* The list for "struct tomoyo_domain_info". */ 895 697 extern struct list_head tomoyo_domain_list; 896 698 897 - extern struct list_head tomoyo_path_group_list; 898 - extern struct list_head tomoyo_domain_initializer_list; 899 - extern struct list_head tomoyo_domain_keeper_list; 900 - extern struct list_head tomoyo_alias_list; 901 - extern struct list_head tomoyo_globally_readable_list; 902 - extern struct list_head tomoyo_pattern_list; 903 - extern struct list_head tomoyo_no_rewrite_list; 904 - extern struct list_head tomoyo_policy_manager_list; 699 + extern struct list_head tomoyo_policy_list[TOMOYO_MAX_POLICY]; 700 + extern struct list_head tomoyo_group_list[TOMOYO_MAX_GROUP]; 905 701 extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; 906 702 907 703 /* Lock for protecting policy. */ ··· 906 714 907 715 /* The kernel's domain. */ 908 716 extern struct tomoyo_domain_info tomoyo_kernel_domain; 717 + 718 + extern const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION]; 719 + extern const char *tomoyo_mkdev_keyword[TOMOYO_MAX_MKDEV_OPERATION]; 720 + extern const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION]; 721 + extern const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION]; 722 + 723 + extern unsigned int tomoyo_quota_for_query; 724 + extern unsigned int tomoyo_query_memory_size; 909 725 910 726 /********** Inlined functions. **********/ 911 727 ··· 935 735 } 936 736 937 737 /** 938 - * tomoyo_is_valid - Check whether the character is a valid char. 738 + * tomoyo_valid - Check whether the character is a valid char. 939 739 * 940 740 * @c: The character to check. 941 741 * 942 742 * Returns true if @c is a valid character, false otherwise. 943 743 */ 944 - static inline bool tomoyo_is_valid(const unsigned char c) 744 + static inline bool tomoyo_valid(const unsigned char c) 945 745 { 946 746 return c > ' ' && c < 127; 947 747 } 948 748 949 749 /** 950 - * tomoyo_is_invalid - Check whether the character is an invalid char. 750 + * tomoyo_invalid - Check whether the character is an invalid char. 951 751 * 952 752 * @c: The character to check. 953 753 * 954 754 * Returns true if @c is an invalid character, false otherwise. 955 755 */ 956 - static inline bool tomoyo_is_invalid(const unsigned char c) 756 + static inline bool tomoyo_invalid(const unsigned char c) 957 757 { 958 758 return c && (c <= ' ' || c >= 127); 959 759 } ··· 961 761 static inline void tomoyo_put_name(const struct tomoyo_path_info *name) 962 762 { 963 763 if (name) { 964 - struct tomoyo_name_entry *ptr = 965 - container_of(name, struct tomoyo_name_entry, entry); 764 + struct tomoyo_name *ptr = 765 + container_of(name, typeof(*ptr), entry); 966 766 atomic_dec(&ptr->users); 967 767 } 968 768 } 969 769 970 - static inline void tomoyo_put_path_group(struct tomoyo_path_group *group) 770 + static inline void tomoyo_put_group(struct tomoyo_group *group) 971 771 { 972 772 if (group) 973 773 atomic_dec(&group->users); ··· 984 784 return task_cred_xxx(task, security); 985 785 } 986 786 987 - static inline bool tomoyo_is_same_acl_head(const struct tomoyo_acl_info *p1, 787 + static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *p1, 988 788 const struct tomoyo_acl_info *p2) 989 789 { 990 790 return p1->type == p2->type; 991 791 } 992 792 993 - static inline bool tomoyo_is_same_name_union 793 + static inline bool tomoyo_same_name_union 994 794 (const struct tomoyo_name_union *p1, const struct tomoyo_name_union *p2) 995 795 { 996 796 return p1->filename == p2->filename && p1->group == p2->group && 997 797 p1->is_group == p2->is_group; 998 798 } 999 799 1000 - static inline bool tomoyo_is_same_path_acl(const struct tomoyo_path_acl *p1, 1001 - const struct tomoyo_path_acl *p2) 800 + static inline bool tomoyo_same_number_union 801 + (const struct tomoyo_number_union *p1, const struct tomoyo_number_union *p2) 1002 802 { 1003 - return tomoyo_is_same_acl_head(&p1->head, &p2->head) && 1004 - tomoyo_is_same_name_union(&p1->name, &p2->name); 1005 - } 1006 - 1007 - static inline bool tomoyo_is_same_path2_acl(const struct tomoyo_path2_acl *p1, 1008 - const struct tomoyo_path2_acl *p2) 1009 - { 1010 - return tomoyo_is_same_acl_head(&p1->head, &p2->head) && 1011 - tomoyo_is_same_name_union(&p1->name1, &p2->name1) && 1012 - tomoyo_is_same_name_union(&p1->name2, &p2->name2); 1013 - } 1014 - 1015 - static inline bool tomoyo_is_same_domain_initializer_entry 1016 - (const struct tomoyo_domain_initializer_entry *p1, 1017 - const struct tomoyo_domain_initializer_entry *p2) 1018 - { 1019 - return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name 1020 - && p1->domainname == p2->domainname 1021 - && p1->program == p2->program; 1022 - } 1023 - 1024 - static inline bool tomoyo_is_same_domain_keeper_entry 1025 - (const struct tomoyo_domain_keeper_entry *p1, 1026 - const struct tomoyo_domain_keeper_entry *p2) 1027 - { 1028 - return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name 1029 - && p1->domainname == p2->domainname 1030 - && p1->program == p2->program; 1031 - } 1032 - 1033 - static inline bool tomoyo_is_same_alias_entry 1034 - (const struct tomoyo_alias_entry *p1, const struct tomoyo_alias_entry *p2) 1035 - { 1036 - return p1->original_name == p2->original_name && 1037 - p1->aliased_name == p2->aliased_name; 803 + return p1->values[0] == p2->values[0] && p1->values[1] == p2->values[1] 804 + && p1->group == p2->group && p1->min_type == p2->min_type && 805 + p1->max_type == p2->max_type && p1->is_group == p2->is_group; 1038 806 } 1039 807 1040 808 /** 1041 809 * list_for_each_cookie - iterate over a list with cookie. 1042 810 * @pos: the &struct list_head to use as a loop cursor. 1043 - * @cookie: the &struct list_head to use as a cookie. 1044 811 * @head: the head for your list. 1045 - * 1046 - * Same with list_for_each_rcu() except that this primitive uses @cookie 1047 - * so that we can continue iteration. 1048 - * @cookie must be NULL when iteration starts, and @cookie will become 1049 - * NULL when iteration finishes. 1050 812 */ 1051 - #define list_for_each_cookie(pos, cookie, head) \ 1052 - for (({ if (!cookie) \ 1053 - cookie = head; }), \ 1054 - pos = rcu_dereference((cookie)->next); \ 1055 - prefetch(pos->next), pos != (head) || ((cookie) = NULL); \ 1056 - (cookie) = pos, pos = rcu_dereference(pos->next)) 813 + #define list_for_each_cookie(pos, head) \ 814 + if (!pos) \ 815 + pos = srcu_dereference((head)->next, &tomoyo_ss); \ 816 + for ( ; pos != (head); pos = srcu_dereference(pos->next, &tomoyo_ss)) 1057 817 1058 818 #endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */
+309 -572
security/tomoyo/domain.c
··· 1 1 /* 2 2 * security/tomoyo/domain.c 3 3 * 4 - * Implementation of the Domain-Based Mandatory Access Control. 4 + * Domain transition functions for TOMOYO. 5 5 * 6 - * Copyright (C) 2005-2009 NTT DATA CORPORATION 7 - * 8 - * Version: 2.2.0 2009/04/01 9 - * 6 + * Copyright (C) 2005-2010 NTT DATA CORPORATION 10 7 */ 11 8 12 9 #include "common.h" ··· 15 18 /* The initial domain. */ 16 19 struct tomoyo_domain_info tomoyo_kernel_domain; 17 20 18 - /* 19 - * tomoyo_domain_list is used for holding list of domains. 20 - * The ->acl_info_list of "struct tomoyo_domain_info" is used for holding 21 - * permissions (e.g. "allow_read /lib/libc-2.5.so") given to each domain. 22 - * 23 - * An entry is added by 24 - * 25 - * # ( echo "<kernel>"; echo "allow_execute /sbin/init" ) > \ 26 - * /sys/kernel/security/tomoyo/domain_policy 27 - * 28 - * and is deleted by 29 - * 30 - * # ( echo "<kernel>"; echo "delete allow_execute /sbin/init" ) > \ 31 - * /sys/kernel/security/tomoyo/domain_policy 32 - * 33 - * and all entries are retrieved by 34 - * 35 - * # cat /sys/kernel/security/tomoyo/domain_policy 36 - * 37 - * A domain is added by 38 - * 39 - * # echo "<kernel>" > /sys/kernel/security/tomoyo/domain_policy 40 - * 41 - * and is deleted by 42 - * 43 - * # echo "delete <kernel>" > /sys/kernel/security/tomoyo/domain_policy 44 - * 45 - * and all domains are retrieved by 46 - * 47 - * # grep '^<kernel>' /sys/kernel/security/tomoyo/domain_policy 48 - * 49 - * Normally, a domainname is monotonically getting longer because a domainname 50 - * which the process will belong to if an execve() operation succeeds is 51 - * defined as a concatenation of "current domainname" + "pathname passed to 52 - * execve()". 53 - * See tomoyo_domain_initializer_list and tomoyo_domain_keeper_list for 54 - * exceptions. 55 - */ 56 - LIST_HEAD(tomoyo_domain_list); 57 - 58 21 /** 59 - * tomoyo_get_last_name - Get last component of a domainname. 22 + * tomoyo_update_policy - Update an entry for exception policy. 60 23 * 61 - * @domain: Pointer to "struct tomoyo_domain_info". 62 - * 63 - * Returns the last component of the domainname. 64 - */ 65 - const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain) 66 - { 67 - const char *cp0 = domain->domainname->name; 68 - const char *cp1 = strrchr(cp0, ' '); 69 - 70 - if (cp1) 71 - return cp1 + 1; 72 - return cp0; 73 - } 74 - 75 - /* 76 - * tomoyo_domain_initializer_list is used for holding list of programs which 77 - * triggers reinitialization of domainname. Normally, a domainname is 78 - * monotonically getting longer. But sometimes, we restart daemon programs. 79 - * It would be convenient for us that "a daemon started upon system boot" and 80 - * "the daemon restarted from console" belong to the same domain. Thus, TOMOYO 81 - * provides a way to shorten domainnames. 82 - * 83 - * An entry is added by 84 - * 85 - * # echo 'initialize_domain /usr/sbin/httpd' > \ 86 - * /sys/kernel/security/tomoyo/exception_policy 87 - * 88 - * and is deleted by 89 - * 90 - * # echo 'delete initialize_domain /usr/sbin/httpd' > \ 91 - * /sys/kernel/security/tomoyo/exception_policy 92 - * 93 - * and all entries are retrieved by 94 - * 95 - * # grep ^initialize_domain /sys/kernel/security/tomoyo/exception_policy 96 - * 97 - * In the example above, /usr/sbin/httpd will belong to 98 - * "<kernel> /usr/sbin/httpd" domain. 99 - * 100 - * You may specify a domainname using "from" keyword. 101 - * "initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd" 102 - * will cause "/usr/sbin/httpd" executed from "<kernel> /etc/rc.d/init.d/httpd" 103 - * domain to belong to "<kernel> /usr/sbin/httpd" domain. 104 - * 105 - * You may add "no_" prefix to "initialize_domain". 106 - * "initialize_domain /usr/sbin/httpd" and 107 - * "no_initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd" 108 - * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain 109 - * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain. 110 - */ 111 - LIST_HEAD(tomoyo_domain_initializer_list); 112 - 113 - /** 114 - * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list. 115 - * 116 - * @domainname: The name of domain. May be NULL. 117 - * @program: The name of program. 118 - * @is_not: True if it is "no_initialize_domain" entry. 119 - * @is_delete: True if it is a delete request. 24 + * @new_entry: Pointer to "struct tomoyo_acl_info". 25 + * @size: Size of @new_entry in bytes. 26 + * @is_delete: True if it is a delete request. 27 + * @list: Pointer to "struct list_head". 28 + * @check_duplicate: Callback function to find duplicated entry. 120 29 * 121 30 * Returns 0 on success, negative value otherwise. 122 31 * 123 32 * Caller holds tomoyo_read_lock(). 124 33 */ 125 - static int tomoyo_update_domain_initializer_entry(const char *domainname, 126 - const char *program, 127 - const bool is_not, 128 - const bool is_delete) 34 + int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, 35 + bool is_delete, struct list_head *list, 36 + bool (*check_duplicate) (const struct tomoyo_acl_head 37 + *, 38 + const struct tomoyo_acl_head 39 + *)) 129 40 { 130 - struct tomoyo_domain_initializer_entry *ptr; 131 - struct tomoyo_domain_initializer_entry e = { .is_not = is_not }; 132 41 int error = is_delete ? -ENOENT : -ENOMEM; 42 + struct tomoyo_acl_head *entry; 133 43 134 - if (!tomoyo_is_correct_path(program, 1, -1, -1)) 135 - return -EINVAL; /* No patterns allowed. */ 136 - if (domainname) { 137 - if (!tomoyo_is_domain_def(domainname) && 138 - tomoyo_is_correct_path(domainname, 1, -1, -1)) 139 - e.is_last_name = true; 140 - else if (!tomoyo_is_correct_domain(domainname)) 141 - return -EINVAL; 142 - e.domainname = tomoyo_get_name(domainname); 143 - if (!e.domainname) 144 - goto out; 145 - } 146 - e.program = tomoyo_get_name(program); 147 - if (!e.program) 148 - goto out; 149 44 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 150 - goto out; 151 - list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { 152 - if (!tomoyo_is_same_domain_initializer_entry(ptr, &e)) 45 + return -ENOMEM; 46 + list_for_each_entry_rcu(entry, list, list) { 47 + if (!check_duplicate(entry, new_entry)) 153 48 continue; 154 - ptr->is_deleted = is_delete; 49 + entry->is_deleted = is_delete; 155 50 error = 0; 156 51 break; 157 52 } 158 - if (!is_delete && error) { 159 - struct tomoyo_domain_initializer_entry *entry = 160 - tomoyo_commit_ok(&e, sizeof(e)); 53 + if (error && !is_delete) { 54 + entry = tomoyo_commit_ok(new_entry, size); 161 55 if (entry) { 162 - list_add_tail_rcu(&entry->list, 163 - &tomoyo_domain_initializer_list); 56 + list_add_tail_rcu(&entry->list, list); 164 57 error = 0; 165 58 } 166 59 } 167 60 mutex_unlock(&tomoyo_policy_lock); 168 - out: 169 - tomoyo_put_name(e.domainname); 170 - tomoyo_put_name(e.program); 171 61 return error; 172 62 } 173 63 174 64 /** 175 - * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list. 65 + * tomoyo_update_domain - Update an entry for domain policy. 176 66 * 177 - * @head: Pointer to "struct tomoyo_io_buffer". 178 - * 179 - * Returns true on success, false otherwise. 180 - * 181 - * Caller holds tomoyo_read_lock(). 182 - */ 183 - bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) 184 - { 185 - struct list_head *pos; 186 - bool done = true; 187 - 188 - list_for_each_cookie(pos, head->read_var2, 189 - &tomoyo_domain_initializer_list) { 190 - const char *no; 191 - const char *from = ""; 192 - const char *domain = ""; 193 - struct tomoyo_domain_initializer_entry *ptr; 194 - ptr = list_entry(pos, struct tomoyo_domain_initializer_entry, 195 - list); 196 - if (ptr->is_deleted) 197 - continue; 198 - no = ptr->is_not ? "no_" : ""; 199 - if (ptr->domainname) { 200 - from = " from "; 201 - domain = ptr->domainname->name; 202 - } 203 - done = tomoyo_io_printf(head, 204 - "%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN 205 - "%s%s%s\n", no, ptr->program->name, 206 - from, domain); 207 - if (!done) 208 - break; 209 - } 210 - return done; 211 - } 212 - 213 - /** 214 - * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list. 215 - * 216 - * @data: String to parse. 217 - * @is_not: True if it is "no_initialize_domain" entry. 218 - * @is_delete: True if it is a delete request. 67 + * @new_entry: Pointer to "struct tomoyo_acl_info". 68 + * @size: Size of @new_entry in bytes. 69 + * @is_delete: True if it is a delete request. 70 + * @domain: Pointer to "struct tomoyo_domain_info". 71 + * @check_duplicate: Callback function to find duplicated entry. 72 + * @merge_duplicate: Callback function to merge duplicated entry. 219 73 * 220 74 * Returns 0 on success, negative value otherwise. 221 75 * 222 76 * Caller holds tomoyo_read_lock(). 223 77 */ 224 - int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, 225 - const bool is_delete) 78 + int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, 79 + bool is_delete, struct tomoyo_domain_info *domain, 80 + bool (*check_duplicate) (const struct tomoyo_acl_info 81 + *, 82 + const struct tomoyo_acl_info 83 + *), 84 + bool (*merge_duplicate) (struct tomoyo_acl_info *, 85 + struct tomoyo_acl_info *, 86 + const bool)) 226 87 { 227 - char *cp = strstr(data, " from "); 88 + int error = is_delete ? -ENOENT : -ENOMEM; 89 + struct tomoyo_acl_info *entry; 228 90 229 - if (cp) { 230 - *cp = '\0'; 231 - return tomoyo_update_domain_initializer_entry(cp + 6, data, 232 - is_not, 233 - is_delete); 91 + if (mutex_lock_interruptible(&tomoyo_policy_lock)) 92 + return error; 93 + list_for_each_entry_rcu(entry, &domain->acl_info_list, list) { 94 + if (!check_duplicate(entry, new_entry)) 95 + continue; 96 + if (merge_duplicate) 97 + entry->is_deleted = merge_duplicate(entry, new_entry, 98 + is_delete); 99 + else 100 + entry->is_deleted = is_delete; 101 + error = 0; 102 + break; 234 103 } 235 - return tomoyo_update_domain_initializer_entry(NULL, data, is_not, 236 - is_delete); 104 + if (error && !is_delete) { 105 + entry = tomoyo_commit_ok(new_entry, size); 106 + if (entry) { 107 + list_add_tail_rcu(&entry->list, &domain->acl_info_list); 108 + error = 0; 109 + } 110 + } 111 + mutex_unlock(&tomoyo_policy_lock); 112 + return error; 113 + } 114 + 115 + void tomoyo_check_acl(struct tomoyo_request_info *r, 116 + bool (*check_entry) (struct tomoyo_request_info *, 117 + const struct tomoyo_acl_info *)) 118 + { 119 + const struct tomoyo_domain_info *domain = r->domain; 120 + struct tomoyo_acl_info *ptr; 121 + 122 + list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 123 + if (ptr->is_deleted || ptr->type != r->param_type) 124 + continue; 125 + if (check_entry(r, ptr)) { 126 + r->granted = true; 127 + return; 128 + } 129 + } 130 + r->granted = false; 131 + } 132 + 133 + /* The list for "struct tomoyo_domain_info". */ 134 + LIST_HEAD(tomoyo_domain_list); 135 + 136 + struct list_head tomoyo_policy_list[TOMOYO_MAX_POLICY]; 137 + struct list_head tomoyo_group_list[TOMOYO_MAX_GROUP]; 138 + 139 + /** 140 + * tomoyo_last_word - Get last component of a domainname. 141 + * 142 + * @domainname: Domainname to check. 143 + * 144 + * Returns the last word of @domainname. 145 + */ 146 + static const char *tomoyo_last_word(const char *name) 147 + { 148 + const char *cp = strrchr(name, ' '); 149 + if (cp) 150 + return cp + 1; 151 + return name; 152 + } 153 + 154 + static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a, 155 + const struct tomoyo_acl_head *b) 156 + { 157 + const struct tomoyo_transition_control *p1 = container_of(a, 158 + typeof(*p1), 159 + head); 160 + const struct tomoyo_transition_control *p2 = container_of(b, 161 + typeof(*p2), 162 + head); 163 + return p1->type == p2->type && p1->is_last_name == p2->is_last_name 164 + && p1->domainname == p2->domainname 165 + && p1->program == p2->program; 237 166 } 238 167 239 168 /** 240 - * tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization. 169 + * tomoyo_update_transition_control_entry - Update "struct tomoyo_transition_control" list. 241 170 * 242 - * @domainname: The name of domain. 243 - * @program: The name of program. 244 - * @last_name: The last component of @domainname. 245 - * 246 - * Returns true if executing @program reinitializes domain transition, 247 - * false otherwise. 248 - * 249 - * Caller holds tomoyo_read_lock(). 250 - */ 251 - static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * 252 - domainname, 253 - const struct tomoyo_path_info *program, 254 - const struct tomoyo_path_info * 255 - last_name) 256 - { 257 - struct tomoyo_domain_initializer_entry *ptr; 258 - bool flag = false; 259 - 260 - list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { 261 - if (ptr->is_deleted) 262 - continue; 263 - if (ptr->domainname) { 264 - if (!ptr->is_last_name) { 265 - if (ptr->domainname != domainname) 266 - continue; 267 - } else { 268 - if (tomoyo_pathcmp(ptr->domainname, last_name)) 269 - continue; 270 - } 271 - } 272 - if (tomoyo_pathcmp(ptr->program, program)) 273 - continue; 274 - if (ptr->is_not) { 275 - flag = false; 276 - break; 277 - } 278 - flag = true; 279 - } 280 - return flag; 281 - } 282 - 283 - /* 284 - * tomoyo_domain_keeper_list is used for holding list of domainnames which 285 - * suppresses domain transition. Normally, a domainname is monotonically 286 - * getting longer. But sometimes, we want to suppress domain transition. 287 - * It would be convenient for us that programs executed from a login session 288 - * belong to the same domain. Thus, TOMOYO provides a way to suppress domain 289 - * transition. 290 - * 291 - * An entry is added by 292 - * 293 - * # echo 'keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \ 294 - * /sys/kernel/security/tomoyo/exception_policy 295 - * 296 - * and is deleted by 297 - * 298 - * # echo 'delete keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \ 299 - * /sys/kernel/security/tomoyo/exception_policy 300 - * 301 - * and all entries are retrieved by 302 - * 303 - * # grep ^keep_domain /sys/kernel/security/tomoyo/exception_policy 304 - * 305 - * In the example above, any process which belongs to 306 - * "<kernel> /usr/sbin/sshd /bin/bash" domain will remain in that domain, 307 - * unless explicitly specified by "initialize_domain" or "no_keep_domain". 308 - * 309 - * You may specify a program using "from" keyword. 310 - * "keep_domain /bin/pwd from <kernel> /usr/sbin/sshd /bin/bash" 311 - * will cause "/bin/pwd" executed from "<kernel> /usr/sbin/sshd /bin/bash" 312 - * domain to remain in "<kernel> /usr/sbin/sshd /bin/bash" domain. 313 - * 314 - * You may add "no_" prefix to "keep_domain". 315 - * "keep_domain <kernel> /usr/sbin/sshd /bin/bash" and 316 - * "no_keep_domain /usr/bin/passwd from <kernel> /usr/sbin/sshd /bin/bash" will 317 - * cause "/usr/bin/passwd" to belong to 318 - * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless 319 - * explicitly specified by "initialize_domain". 320 - */ 321 - LIST_HEAD(tomoyo_domain_keeper_list); 322 - 323 - /** 324 - * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list. 325 - * 326 - * @domainname: The name of domain. 327 - * @program: The name of program. May be NULL. 328 - * @is_not: True if it is "no_keep_domain" entry. 171 + * @domainname: The name of domain. Maybe NULL. 172 + * @program: The name of program. Maybe NULL. 173 + * @type: Type of transition. 329 174 * @is_delete: True if it is a delete request. 330 175 * 331 176 * Returns 0 on success, negative value otherwise. 332 - * 333 - * Caller holds tomoyo_read_lock(). 334 177 */ 335 - static int tomoyo_update_domain_keeper_entry(const char *domainname, 336 - const char *program, 337 - const bool is_not, 338 - const bool is_delete) 178 + static int tomoyo_update_transition_control_entry(const char *domainname, 179 + const char *program, 180 + const u8 type, 181 + const bool is_delete) 339 182 { 340 - struct tomoyo_domain_keeper_entry *ptr; 341 - struct tomoyo_domain_keeper_entry e = { .is_not = is_not }; 183 + struct tomoyo_transition_control e = { .type = type }; 342 184 int error = is_delete ? -ENOENT : -ENOMEM; 343 - 344 - if (!tomoyo_is_domain_def(domainname) && 345 - tomoyo_is_correct_path(domainname, 1, -1, -1)) 346 - e.is_last_name = true; 347 - else if (!tomoyo_is_correct_domain(domainname)) 348 - return -EINVAL; 349 185 if (program) { 350 - if (!tomoyo_is_correct_path(program, 1, -1, -1)) 186 + if (!tomoyo_correct_path(program)) 351 187 return -EINVAL; 352 188 e.program = tomoyo_get_name(program); 353 189 if (!e.program) 354 190 goto out; 355 191 } 356 - e.domainname = tomoyo_get_name(domainname); 357 - if (!e.domainname) 358 - goto out; 359 - if (mutex_lock_interruptible(&tomoyo_policy_lock)) 360 - goto out; 361 - list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { 362 - if (!tomoyo_is_same_domain_keeper_entry(ptr, &e)) 363 - continue; 364 - ptr->is_deleted = is_delete; 365 - error = 0; 366 - break; 367 - } 368 - if (!is_delete && error) { 369 - struct tomoyo_domain_keeper_entry *entry = 370 - tomoyo_commit_ok(&e, sizeof(e)); 371 - if (entry) { 372 - list_add_tail_rcu(&entry->list, 373 - &tomoyo_domain_keeper_list); 374 - error = 0; 192 + if (domainname) { 193 + if (!tomoyo_correct_domain(domainname)) { 194 + if (!tomoyo_correct_path(domainname)) 195 + goto out; 196 + e.is_last_name = true; 375 197 } 198 + e.domainname = tomoyo_get_name(domainname); 199 + if (!e.domainname) 200 + goto out; 376 201 } 377 - mutex_unlock(&tomoyo_policy_lock); 202 + error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 203 + &tomoyo_policy_list 204 + [TOMOYO_ID_TRANSITION_CONTROL], 205 + tomoyo_same_transition_control); 378 206 out: 379 207 tomoyo_put_name(e.domainname); 380 208 tomoyo_put_name(e.program); ··· 207 385 } 208 386 209 387 /** 210 - * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list. 388 + * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list. 211 389 * 212 390 * @data: String to parse. 213 - * @is_not: True if it is "no_keep_domain" entry. 214 391 * @is_delete: True if it is a delete request. 392 + * @type: Type of this entry. 215 393 * 216 - * Caller holds tomoyo_read_lock(). 394 + * Returns 0 on success, negative value otherwise. 217 395 */ 218 - int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, 219 - const bool is_delete) 396 + int tomoyo_write_transition_control(char *data, const bool is_delete, 397 + const u8 type) 220 398 { 221 - char *cp = strstr(data, " from "); 222 - 223 - if (cp) { 224 - *cp = '\0'; 225 - return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not, 226 - is_delete); 399 + char *domainname = strstr(data, " from "); 400 + if (domainname) { 401 + *domainname = '\0'; 402 + domainname += 6; 403 + } else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP || 404 + type == TOMOYO_TRANSITION_CONTROL_KEEP) { 405 + domainname = data; 406 + data = NULL; 227 407 } 228 - return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete); 408 + return tomoyo_update_transition_control_entry(domainname, data, type, 409 + is_delete); 229 410 } 230 411 231 412 /** 232 - * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list. 233 - * 234 - * @head: Pointer to "struct tomoyo_io_buffer". 235 - * 236 - * Returns true on success, false otherwise. 237 - * 238 - * Caller holds tomoyo_read_lock(). 239 - */ 240 - bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) 241 - { 242 - struct list_head *pos; 243 - bool done = true; 244 - 245 - list_for_each_cookie(pos, head->read_var2, 246 - &tomoyo_domain_keeper_list) { 247 - struct tomoyo_domain_keeper_entry *ptr; 248 - const char *no; 249 - const char *from = ""; 250 - const char *program = ""; 251 - 252 - ptr = list_entry(pos, struct tomoyo_domain_keeper_entry, list); 253 - if (ptr->is_deleted) 254 - continue; 255 - no = ptr->is_not ? "no_" : ""; 256 - if (ptr->program) { 257 - from = " from "; 258 - program = ptr->program->name; 259 - } 260 - done = tomoyo_io_printf(head, 261 - "%s" TOMOYO_KEYWORD_KEEP_DOMAIN 262 - "%s%s%s\n", no, program, from, 263 - ptr->domainname->name); 264 - if (!done) 265 - break; 266 - } 267 - return done; 268 - } 269 - 270 - /** 271 - * tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression. 413 + * tomoyo_transition_type - Get domain transition type. 272 414 * 273 415 * @domainname: The name of domain. 274 416 * @program: The name of program. 275 - * @last_name: The last component of @domainname. 276 417 * 277 - * Returns true if executing @program supresses domain transition, 278 - * false otherwise. 418 + * Returns TOMOYO_TRANSITION_CONTROL_INITIALIZE if executing @program 419 + * reinitializes domain transition, TOMOYO_TRANSITION_CONTROL_KEEP if executing 420 + * @program suppresses domain transition, others otherwise. 279 421 * 280 422 * Caller holds tomoyo_read_lock(). 281 423 */ 282 - static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, 283 - const struct tomoyo_path_info *program, 284 - const struct tomoyo_path_info *last_name) 424 + static u8 tomoyo_transition_type(const struct tomoyo_path_info *domainname, 425 + const struct tomoyo_path_info *program) 285 426 { 286 - struct tomoyo_domain_keeper_entry *ptr; 287 - bool flag = false; 288 - 289 - list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { 290 - if (ptr->is_deleted) 291 - continue; 292 - if (!ptr->is_last_name) { 293 - if (ptr->domainname != domainname) 427 + const struct tomoyo_transition_control *ptr; 428 + const char *last_name = tomoyo_last_word(domainname->name); 429 + u8 type; 430 + for (type = 0; type < TOMOYO_MAX_TRANSITION_TYPE; type++) { 431 + next: 432 + list_for_each_entry_rcu(ptr, &tomoyo_policy_list 433 + [TOMOYO_ID_TRANSITION_CONTROL], 434 + head.list) { 435 + if (ptr->head.is_deleted || ptr->type != type) 294 436 continue; 295 - } else { 296 - if (tomoyo_pathcmp(ptr->domainname, last_name)) 437 + if (ptr->domainname) { 438 + if (!ptr->is_last_name) { 439 + if (ptr->domainname != domainname) 440 + continue; 441 + } else { 442 + /* 443 + * Use direct strcmp() since this is 444 + * unlikely used. 445 + */ 446 + if (strcmp(ptr->domainname->name, 447 + last_name)) 448 + continue; 449 + } 450 + } 451 + if (ptr->program && 452 + tomoyo_pathcmp(ptr->program, program)) 297 453 continue; 454 + if (type == TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE) { 455 + /* 456 + * Do not check for initialize_domain if 457 + * no_initialize_domain matched. 458 + */ 459 + type = TOMOYO_TRANSITION_CONTROL_NO_KEEP; 460 + goto next; 461 + } 462 + goto done; 298 463 } 299 - if (ptr->program && tomoyo_pathcmp(ptr->program, program)) 300 - continue; 301 - if (ptr->is_not) { 302 - flag = false; 303 - break; 304 - } 305 - flag = true; 306 464 } 307 - return flag; 465 + done: 466 + return type; 308 467 } 309 468 310 - /* 311 - * tomoyo_alias_list is used for holding list of symlink's pathnames which are 312 - * allowed to be passed to an execve() request. Normally, the domainname which 313 - * the current process will belong to after execve() succeeds is calculated 314 - * using dereferenced pathnames. But some programs behave differently depending 315 - * on the name passed to argv[0]. For busybox, calculating domainname using 316 - * dereferenced pathnames will cause all programs in the busybox to belong to 317 - * the same domain. Thus, TOMOYO provides a way to allow use of symlink's 318 - * pathname for checking execve()'s permission and calculating domainname which 319 - * the current process will belong to after execve() succeeds. 320 - * 321 - * An entry is added by 322 - * 323 - * # echo 'alias /bin/busybox /bin/cat' > \ 324 - * /sys/kernel/security/tomoyo/exception_policy 325 - * 326 - * and is deleted by 327 - * 328 - * # echo 'delete alias /bin/busybox /bin/cat' > \ 329 - * /sys/kernel/security/tomoyo/exception_policy 330 - * 331 - * and all entries are retrieved by 332 - * 333 - * # grep ^alias /sys/kernel/security/tomoyo/exception_policy 334 - * 335 - * In the example above, if /bin/cat is a symlink to /bin/busybox and execution 336 - * of /bin/cat is requested, permission is checked for /bin/cat rather than 337 - * /bin/busybox and domainname which the current process will belong to after 338 - * execve() succeeds is calculated using /bin/cat rather than /bin/busybox . 339 - */ 340 - LIST_HEAD(tomoyo_alias_list); 469 + static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a, 470 + const struct tomoyo_acl_head *b) 471 + { 472 + const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1), head); 473 + const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2), head); 474 + return p1->original_name == p2->original_name && 475 + p1->aggregated_name == p2->aggregated_name; 476 + } 341 477 342 478 /** 343 - * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list. 479 + * tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator" list. 344 480 * 345 - * @original_name: The original program's real name. 346 - * @aliased_name: The symbolic program's symbolic link's name. 347 - * @is_delete: True if it is a delete request. 481 + * @original_name: The original program's name. 482 + * @aggregated_name: The program name to use. 483 + * @is_delete: True if it is a delete request. 348 484 * 349 485 * Returns 0 on success, negative value otherwise. 350 486 * 351 487 * Caller holds tomoyo_read_lock(). 352 488 */ 353 - static int tomoyo_update_alias_entry(const char *original_name, 354 - const char *aliased_name, 355 - const bool is_delete) 489 + static int tomoyo_update_aggregator_entry(const char *original_name, 490 + const char *aggregated_name, 491 + const bool is_delete) 356 492 { 357 - struct tomoyo_alias_entry *ptr; 358 - struct tomoyo_alias_entry e = { }; 493 + struct tomoyo_aggregator e = { }; 359 494 int error = is_delete ? -ENOENT : -ENOMEM; 360 495 361 - if (!tomoyo_is_correct_path(original_name, 1, -1, -1) || 362 - !tomoyo_is_correct_path(aliased_name, 1, -1, -1)) 363 - return -EINVAL; /* No patterns allowed. */ 496 + if (!tomoyo_correct_path(original_name) || 497 + !tomoyo_correct_path(aggregated_name)) 498 + return -EINVAL; 364 499 e.original_name = tomoyo_get_name(original_name); 365 - e.aliased_name = tomoyo_get_name(aliased_name); 366 - if (!e.original_name || !e.aliased_name) 500 + e.aggregated_name = tomoyo_get_name(aggregated_name); 501 + if (!e.original_name || !e.aggregated_name || 502 + e.aggregated_name->is_patterned) /* No patterns allowed. */ 367 503 goto out; 368 - if (mutex_lock_interruptible(&tomoyo_policy_lock)) 369 - goto out; 370 - list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { 371 - if (!tomoyo_is_same_alias_entry(ptr, &e)) 372 - continue; 373 - ptr->is_deleted = is_delete; 374 - error = 0; 375 - break; 376 - } 377 - if (!is_delete && error) { 378 - struct tomoyo_alias_entry *entry = 379 - tomoyo_commit_ok(&e, sizeof(e)); 380 - if (entry) { 381 - list_add_tail_rcu(&entry->list, &tomoyo_alias_list); 382 - error = 0; 383 - } 384 - } 385 - mutex_unlock(&tomoyo_policy_lock); 504 + error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 505 + &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR], 506 + tomoyo_same_aggregator); 386 507 out: 387 508 tomoyo_put_name(e.original_name); 388 - tomoyo_put_name(e.aliased_name); 509 + tomoyo_put_name(e.aggregated_name); 389 510 return error; 390 511 } 391 512 392 513 /** 393 - * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list. 394 - * 395 - * @head: Pointer to "struct tomoyo_io_buffer". 396 - * 397 - * Returns true on success, false otherwise. 398 - * 399 - * Caller holds tomoyo_read_lock(). 400 - */ 401 - bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) 402 - { 403 - struct list_head *pos; 404 - bool done = true; 405 - 406 - list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) { 407 - struct tomoyo_alias_entry *ptr; 408 - 409 - ptr = list_entry(pos, struct tomoyo_alias_entry, list); 410 - if (ptr->is_deleted) 411 - continue; 412 - done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n", 413 - ptr->original_name->name, 414 - ptr->aliased_name->name); 415 - if (!done) 416 - break; 417 - } 418 - return done; 419 - } 420 - 421 - /** 422 - * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list. 514 + * tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list. 423 515 * 424 516 * @data: String to parse. 425 517 * @is_delete: True if it is a delete request. ··· 342 606 * 343 607 * Caller holds tomoyo_read_lock(). 344 608 */ 345 - int tomoyo_write_alias_policy(char *data, const bool is_delete) 609 + int tomoyo_write_aggregator(char *data, const bool is_delete) 346 610 { 347 611 char *cp = strchr(data, ' '); 348 612 349 613 if (!cp) 350 614 return -EINVAL; 351 615 *cp++ = '\0'; 352 - return tomoyo_update_alias_entry(data, cp, is_delete); 616 + return tomoyo_update_aggregator_entry(data, cp, is_delete); 353 617 } 354 618 355 619 /** 356 - * tomoyo_find_or_assign_new_domain - Create a domain. 620 + * tomoyo_assign_domain - Create a domain. 357 621 * 358 622 * @domainname: The name of domain. 359 623 * @profile: Profile number to assign if the domain was newly created. ··· 362 626 * 363 627 * Caller holds tomoyo_read_lock(). 364 628 */ 365 - struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * 366 - domainname, 367 - const u8 profile) 629 + struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, 630 + const u8 profile) 368 631 { 369 632 struct tomoyo_domain_info *entry; 370 633 struct tomoyo_domain_info *domain = NULL; 371 634 const struct tomoyo_path_info *saved_domainname; 372 635 bool found = false; 373 636 374 - if (!tomoyo_is_correct_domain(domainname)) 637 + if (!tomoyo_correct_domain(domainname)) 375 638 return NULL; 376 639 saved_domainname = tomoyo_get_name(domainname); 377 640 if (!saved_domainname) ··· 413 678 */ 414 679 int tomoyo_find_next_domain(struct linux_binprm *bprm) 415 680 { 416 - /* 417 - * This function assumes that the size of buffer returned by 418 - * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN. 419 - */ 420 - struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_NOFS); 681 + struct tomoyo_request_info r; 682 + char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS); 421 683 struct tomoyo_domain_info *old_domain = tomoyo_domain(); 422 684 struct tomoyo_domain_info *domain = NULL; 423 - const char *old_domain_name = old_domain->domainname->name; 424 685 const char *original_name = bprm->filename; 425 - char *new_domain_name = NULL; 426 - char *real_program_name = NULL; 427 - char *symlink_program_name = NULL; 428 - const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE); 429 - const bool is_enforce = (mode == 3); 686 + u8 mode; 687 + bool is_enforce; 430 688 int retval = -ENOMEM; 431 - struct tomoyo_path_info r; /* real name */ 432 - struct tomoyo_path_info s; /* symlink name */ 433 - struct tomoyo_path_info l; /* last name */ 434 - static bool initialized; 689 + bool need_kfree = false; 690 + struct tomoyo_path_info rn = { }; /* real name */ 435 691 692 + mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE); 693 + is_enforce = (mode == TOMOYO_CONFIG_ENFORCING); 436 694 if (!tmp) 437 695 goto out; 438 696 439 - if (!initialized) { 440 - /* 441 - * Built-in initializers. This is needed because policies are 442 - * not loaded until starting /sbin/init. 443 - */ 444 - tomoyo_update_domain_initializer_entry(NULL, "/sbin/hotplug", 445 - false, false); 446 - tomoyo_update_domain_initializer_entry(NULL, "/sbin/modprobe", 447 - false, false); 448 - initialized = true; 697 + retry: 698 + if (need_kfree) { 699 + kfree(rn.name); 700 + need_kfree = false; 449 701 } 450 - 451 - /* Get tomoyo_realpath of program. */ 702 + /* Get symlink's pathname of program. */ 452 703 retval = -ENOENT; 453 - /* I hope tomoyo_realpath() won't fail with -ENOMEM. */ 454 - real_program_name = tomoyo_realpath(original_name); 455 - if (!real_program_name) 704 + rn.name = tomoyo_realpath_nofollow(original_name); 705 + if (!rn.name) 456 706 goto out; 457 - /* Get tomoyo_realpath of symbolic link. */ 458 - symlink_program_name = tomoyo_realpath_nofollow(original_name); 459 - if (!symlink_program_name) 460 - goto out; 707 + tomoyo_fill_path_info(&rn); 708 + need_kfree = true; 461 709 462 - r.name = real_program_name; 463 - tomoyo_fill_path_info(&r); 464 - s.name = symlink_program_name; 465 - tomoyo_fill_path_info(&s); 466 - l.name = tomoyo_get_last_name(old_domain); 467 - tomoyo_fill_path_info(&l); 468 - 469 - /* Check 'alias' directive. */ 470 - if (tomoyo_pathcmp(&r, &s)) { 471 - struct tomoyo_alias_entry *ptr; 472 - /* Is this program allowed to be called via symbolic links? */ 473 - list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { 474 - if (ptr->is_deleted || 475 - tomoyo_pathcmp(&r, ptr->original_name) || 476 - tomoyo_pathcmp(&s, ptr->aliased_name)) 710 + /* Check 'aggregator' directive. */ 711 + { 712 + struct tomoyo_aggregator *ptr; 713 + list_for_each_entry_rcu(ptr, &tomoyo_policy_list 714 + [TOMOYO_ID_AGGREGATOR], head.list) { 715 + if (ptr->head.is_deleted || 716 + !tomoyo_path_matches_pattern(&rn, 717 + ptr->original_name)) 477 718 continue; 478 - memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN); 479 - strncpy(real_program_name, ptr->aliased_name->name, 480 - TOMOYO_MAX_PATHNAME_LEN - 1); 481 - tomoyo_fill_path_info(&r); 719 + kfree(rn.name); 720 + need_kfree = false; 721 + /* This is OK because it is read only. */ 722 + rn = *ptr->aggregated_name; 482 723 break; 483 724 } 484 725 } 485 726 486 727 /* Check execute permission. */ 487 - retval = tomoyo_check_exec_perm(old_domain, &r); 728 + retval = tomoyo_path_permission(&r, TOMOYO_TYPE_EXECUTE, &rn); 729 + if (retval == TOMOYO_RETRY_REQUEST) 730 + goto retry; 488 731 if (retval < 0) 489 732 goto out; 733 + /* 734 + * To be able to specify domainnames with wildcards, use the 735 + * pathname specified in the policy (which may contain 736 + * wildcard) rather than the pathname passed to execve() 737 + * (which never contains wildcard). 738 + */ 739 + if (r.param.path.matched_path) { 740 + if (need_kfree) 741 + kfree(rn.name); 742 + need_kfree = false; 743 + /* This is OK because it is read only. */ 744 + rn = *r.param.path.matched_path; 745 + } 490 746 491 - new_domain_name = tmp->buffer; 492 - if (tomoyo_is_domain_initializer(old_domain->domainname, &r, &l)) { 747 + /* Calculate domain to transit to. */ 748 + switch (tomoyo_transition_type(old_domain->domainname, &rn)) { 749 + case TOMOYO_TRANSITION_CONTROL_INITIALIZE: 493 750 /* Transit to the child of tomoyo_kernel_domain domain. */ 494 - snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1, 495 - TOMOYO_ROOT_NAME " " "%s", real_program_name); 496 - } else if (old_domain == &tomoyo_kernel_domain && 497 - !tomoyo_policy_loaded) { 498 - /* 499 - * Needn't to transit from kernel domain before starting 500 - * /sbin/init. But transit from kernel domain if executing 501 - * initializers because they might start before /sbin/init. 502 - */ 503 - domain = old_domain; 504 - } else if (tomoyo_is_domain_keeper(old_domain->domainname, &r, &l)) { 751 + snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, TOMOYO_ROOT_NAME " " 752 + "%s", rn.name); 753 + break; 754 + case TOMOYO_TRANSITION_CONTROL_KEEP: 505 755 /* Keep current domain. */ 506 756 domain = old_domain; 507 - } else { 508 - /* Normal domain transition. */ 509 - snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1, 510 - "%s %s", old_domain_name, real_program_name); 757 + break; 758 + default: 759 + if (old_domain == &tomoyo_kernel_domain && 760 + !tomoyo_policy_loaded) { 761 + /* 762 + * Needn't to transit from kernel domain before 763 + * starting /sbin/init. But transit from kernel domain 764 + * if executing initializers because they might start 765 + * before /sbin/init. 766 + */ 767 + domain = old_domain; 768 + } else { 769 + /* Normal domain transition. */ 770 + snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", 771 + old_domain->domainname->name, rn.name); 772 + } 773 + break; 511 774 } 512 - if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN) 775 + if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10) 513 776 goto done; 514 - domain = tomoyo_find_domain(new_domain_name); 777 + domain = tomoyo_find_domain(tmp); 515 778 if (domain) 516 779 goto done; 517 - if (is_enforce) 518 - goto done; 519 - domain = tomoyo_find_or_assign_new_domain(new_domain_name, 520 - old_domain->profile); 780 + if (is_enforce) { 781 + int error = tomoyo_supervisor(&r, "# wants to create domain\n" 782 + "%s\n", tmp); 783 + if (error == TOMOYO_RETRY_REQUEST) 784 + goto retry; 785 + if (error < 0) 786 + goto done; 787 + } 788 + domain = tomoyo_assign_domain(tmp, old_domain->profile); 521 789 done: 522 790 if (domain) 523 791 goto out; 524 - printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", 525 - new_domain_name); 792 + printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", tmp); 526 793 if (is_enforce) 527 794 retval = -EPERM; 528 795 else ··· 535 798 /* Update reference count on "struct tomoyo_domain_info". */ 536 799 atomic_inc(&domain->users); 537 800 bprm->cred->security = domain; 538 - kfree(real_program_name); 539 - kfree(symlink_program_name); 801 + if (need_kfree) 802 + kfree(rn.name); 540 803 kfree(tmp); 541 804 return retval; 542 805 }
+742 -851
security/tomoyo/file.c
··· 1 1 /* 2 2 * security/tomoyo/file.c 3 3 * 4 - * Implementation of the Domain-Based Mandatory Access Control. 4 + * Pathname restriction functions. 5 5 * 6 - * Copyright (C) 2005-2009 NTT DATA CORPORATION 7 - * 8 - * Version: 2.2.0 2009/04/01 9 - * 6 + * Copyright (C) 2005-2010 NTT DATA CORPORATION 10 7 */ 11 8 12 9 #include "common.h" 13 10 #include <linux/slab.h> 14 11 15 - /* Keyword array for single path operations. */ 16 - static const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { 12 + /* Keyword array for operations with one pathname. */ 13 + const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { 17 14 [TOMOYO_TYPE_READ_WRITE] = "read/write", 18 15 [TOMOYO_TYPE_EXECUTE] = "execute", 19 16 [TOMOYO_TYPE_READ] = "read", 20 17 [TOMOYO_TYPE_WRITE] = "write", 21 - [TOMOYO_TYPE_CREATE] = "create", 22 18 [TOMOYO_TYPE_UNLINK] = "unlink", 23 - [TOMOYO_TYPE_MKDIR] = "mkdir", 24 19 [TOMOYO_TYPE_RMDIR] = "rmdir", 25 - [TOMOYO_TYPE_MKFIFO] = "mkfifo", 26 - [TOMOYO_TYPE_MKSOCK] = "mksock", 27 - [TOMOYO_TYPE_MKBLOCK] = "mkblock", 28 - [TOMOYO_TYPE_MKCHAR] = "mkchar", 29 20 [TOMOYO_TYPE_TRUNCATE] = "truncate", 30 21 [TOMOYO_TYPE_SYMLINK] = "symlink", 31 22 [TOMOYO_TYPE_REWRITE] = "rewrite", 23 + [TOMOYO_TYPE_CHROOT] = "chroot", 24 + [TOMOYO_TYPE_UMOUNT] = "unmount", 25 + }; 26 + 27 + /* Keyword array for operations with one pathname and three numbers. */ 28 + const char *tomoyo_mkdev_keyword[TOMOYO_MAX_MKDEV_OPERATION] = { 29 + [TOMOYO_TYPE_MKBLOCK] = "mkblock", 30 + [TOMOYO_TYPE_MKCHAR] = "mkchar", 31 + }; 32 + 33 + /* Keyword array for operations with two pathnames. */ 34 + const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = { 35 + [TOMOYO_TYPE_LINK] = "link", 36 + [TOMOYO_TYPE_RENAME] = "rename", 37 + [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root", 38 + }; 39 + 40 + /* Keyword array for operations with one pathname and one number. */ 41 + const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { 42 + [TOMOYO_TYPE_CREATE] = "create", 43 + [TOMOYO_TYPE_MKDIR] = "mkdir", 44 + [TOMOYO_TYPE_MKFIFO] = "mkfifo", 45 + [TOMOYO_TYPE_MKSOCK] = "mksock", 32 46 [TOMOYO_TYPE_IOCTL] = "ioctl", 33 47 [TOMOYO_TYPE_CHMOD] = "chmod", 34 48 [TOMOYO_TYPE_CHOWN] = "chown", 35 49 [TOMOYO_TYPE_CHGRP] = "chgrp", 36 - [TOMOYO_TYPE_CHROOT] = "chroot", 37 - [TOMOYO_TYPE_MOUNT] = "mount", 38 - [TOMOYO_TYPE_UMOUNT] = "unmount", 39 50 }; 40 51 41 - /* Keyword array for double path operations. */ 42 - static const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = { 43 - [TOMOYO_TYPE_LINK] = "link", 44 - [TOMOYO_TYPE_RENAME] = "rename", 45 - [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root", 52 + static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { 53 + [TOMOYO_TYPE_READ_WRITE] = TOMOYO_MAC_FILE_OPEN, 54 + [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE, 55 + [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN, 56 + [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN, 57 + [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK, 58 + [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR, 59 + [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE, 60 + [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK, 61 + [TOMOYO_TYPE_REWRITE] = TOMOYO_MAC_FILE_REWRITE, 62 + [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT, 63 + [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT, 64 + }; 65 + 66 + static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = { 67 + [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK, 68 + [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR, 69 + }; 70 + 71 + static const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = { 72 + [TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK, 73 + [TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME, 74 + [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT, 75 + }; 76 + 77 + static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { 78 + [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE, 79 + [TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR, 80 + [TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO, 81 + [TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK, 82 + [TOMOYO_TYPE_IOCTL] = TOMOYO_MAC_FILE_IOCTL, 83 + [TOMOYO_TYPE_CHMOD] = TOMOYO_MAC_FILE_CHMOD, 84 + [TOMOYO_TYPE_CHOWN] = TOMOYO_MAC_FILE_CHOWN, 85 + [TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP, 46 86 }; 47 87 48 88 void tomoyo_put_name_union(struct tomoyo_name_union *ptr) ··· 90 50 if (!ptr) 91 51 return; 92 52 if (ptr->is_group) 93 - tomoyo_put_path_group(ptr->group); 53 + tomoyo_put_group(ptr->group); 94 54 else 95 55 tomoyo_put_name(ptr->filename); 96 56 } 97 57 98 - bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, 99 - const struct tomoyo_name_union *ptr) 58 + const struct tomoyo_path_info * 59 + tomoyo_compare_name_union(const struct tomoyo_path_info *name, 60 + const struct tomoyo_name_union *ptr) 100 61 { 101 62 if (ptr->is_group) 102 - return tomoyo_path_matches_group(name, ptr->group, 1); 103 - return tomoyo_path_matches_pattern(name, ptr->filename); 63 + return tomoyo_path_matches_group(name, ptr->group); 64 + if (tomoyo_path_matches_pattern(name, ptr->filename)) 65 + return ptr->filename; 66 + return NULL; 104 67 } 105 68 106 - static bool tomoyo_compare_name_union_pattern(const struct tomoyo_path_info 107 - *name, 108 - const struct tomoyo_name_union 109 - *ptr, const bool may_use_pattern) 69 + void tomoyo_put_number_union(struct tomoyo_number_union *ptr) 70 + { 71 + if (ptr && ptr->is_group) 72 + tomoyo_put_group(ptr->group); 73 + } 74 + 75 + bool tomoyo_compare_number_union(const unsigned long value, 76 + const struct tomoyo_number_union *ptr) 110 77 { 111 78 if (ptr->is_group) 112 - return tomoyo_path_matches_group(name, ptr->group, 113 - may_use_pattern); 114 - if (may_use_pattern || !ptr->filename->is_patterned) 115 - return tomoyo_path_matches_pattern(name, ptr->filename); 116 - return false; 79 + return tomoyo_number_matches_group(value, value, ptr->group); 80 + return value >= ptr->values[0] && value <= ptr->values[1]; 117 81 } 118 82 119 - /** 120 - * tomoyo_path2keyword - Get the name of single path operation. 121 - * 122 - * @operation: Type of operation. 123 - * 124 - * Returns the name of single path operation. 125 - */ 126 - const char *tomoyo_path2keyword(const u8 operation) 83 + static void tomoyo_add_slash(struct tomoyo_path_info *buf) 127 84 { 128 - return (operation < TOMOYO_MAX_PATH_OPERATION) 129 - ? tomoyo_path_keyword[operation] : NULL; 130 - } 131 - 132 - /** 133 - * tomoyo_path22keyword - Get the name of double path operation. 134 - * 135 - * @operation: Type of operation. 136 - * 137 - * Returns the name of double path operation. 138 - */ 139 - const char *tomoyo_path22keyword(const u8 operation) 140 - { 141 - return (operation < TOMOYO_MAX_PATH2_OPERATION) 142 - ? tomoyo_path2_keyword[operation] : NULL; 85 + if (buf->is_dir) 86 + return; 87 + /* 88 + * This is OK because tomoyo_encode() reserves space for appending "/". 89 + */ 90 + strcat((char *) buf->name, "/"); 91 + tomoyo_fill_path_info(buf); 143 92 } 144 93 145 94 /** ··· 150 121 } 151 122 152 123 /** 153 - * tomoyo_get_path - Get realpath. 124 + * tomoyo_get_realpath - Get realpath. 154 125 * 126 + * @buf: Pointer to "struct tomoyo_path_info". 155 127 * @path: Pointer to "struct path". 156 128 * 157 - * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. 129 + * Returns true on success, false otherwise. 158 130 */ 159 - static struct tomoyo_path_info *tomoyo_get_path(struct path *path) 131 + static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path) 160 132 { 161 - int error; 162 - struct tomoyo_path_info_with_data *buf = kzalloc(sizeof(*buf), 163 - GFP_NOFS); 164 - 165 - if (!buf) 166 - return NULL; 167 - /* Reserve one byte for appending "/". */ 168 - error = tomoyo_realpath_from_path2(path, buf->body, 169 - sizeof(buf->body) - 2); 170 - if (!error) { 171 - buf->head.name = buf->body; 172 - tomoyo_fill_path_info(&buf->head); 173 - return &buf->head; 133 + buf->name = tomoyo_realpath_from_path(path); 134 + if (buf->name) { 135 + tomoyo_fill_path_info(buf); 136 + return true; 174 137 } 175 - kfree(buf); 176 - return NULL; 138 + return false; 177 139 } 178 140 179 - static int tomoyo_update_path2_acl(const u8 type, const char *filename1, 180 - const char *filename2, 181 - struct tomoyo_domain_info *const domain, 182 - const bool is_delete); 183 - static int tomoyo_update_path_acl(const u8 type, const char *filename, 184 - struct tomoyo_domain_info *const domain, 185 - const bool is_delete); 186 - 187 - /* 188 - * tomoyo_globally_readable_list is used for holding list of pathnames which 189 - * are by default allowed to be open()ed for reading by any process. 141 + /** 142 + * tomoyo_audit_path_log - Audit path request log. 190 143 * 191 - * An entry is added by 144 + * @r: Pointer to "struct tomoyo_request_info". 192 145 * 193 - * # echo 'allow_read /lib/libc-2.5.so' > \ 194 - * /sys/kernel/security/tomoyo/exception_policy 195 - * 196 - * and is deleted by 197 - * 198 - * # echo 'delete allow_read /lib/libc-2.5.so' > \ 199 - * /sys/kernel/security/tomoyo/exception_policy 200 - * 201 - * and all entries are retrieved by 202 - * 203 - * # grep ^allow_read /sys/kernel/security/tomoyo/exception_policy 204 - * 205 - * In the example above, any process is allowed to 206 - * open("/lib/libc-2.5.so", O_RDONLY). 207 - * One exception is, if the domain which current process belongs to is marked 208 - * as "ignore_global_allow_read", current process can't do so unless explicitly 209 - * given "allow_read /lib/libc-2.5.so" to the domain which current process 210 - * belongs to. 146 + * Returns 0 on success, negative value otherwise. 211 147 */ 212 - LIST_HEAD(tomoyo_globally_readable_list); 148 + static int tomoyo_audit_path_log(struct tomoyo_request_info *r) 149 + { 150 + const char *operation = tomoyo_path_keyword[r->param.path.operation]; 151 + const struct tomoyo_path_info *filename = r->param.path.filename; 152 + if (r->granted) 153 + return 0; 154 + tomoyo_warn_log(r, "%s %s", operation, filename->name); 155 + return tomoyo_supervisor(r, "allow_%s %s\n", operation, 156 + tomoyo_pattern(filename)); 157 + } 213 158 214 159 /** 215 - * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list. 160 + * tomoyo_audit_path2_log - Audit path/path request log. 161 + * 162 + * @r: Pointer to "struct tomoyo_request_info". 163 + * 164 + * Returns 0 on success, negative value otherwise. 165 + */ 166 + static int tomoyo_audit_path2_log(struct tomoyo_request_info *r) 167 + { 168 + const char *operation = tomoyo_path2_keyword[r->param.path2.operation]; 169 + const struct tomoyo_path_info *filename1 = r->param.path2.filename1; 170 + const struct tomoyo_path_info *filename2 = r->param.path2.filename2; 171 + if (r->granted) 172 + return 0; 173 + tomoyo_warn_log(r, "%s %s %s", operation, filename1->name, 174 + filename2->name); 175 + return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, 176 + tomoyo_pattern(filename1), 177 + tomoyo_pattern(filename2)); 178 + } 179 + 180 + /** 181 + * tomoyo_audit_mkdev_log - Audit path/number/number/number request log. 182 + * 183 + * @r: Pointer to "struct tomoyo_request_info". 184 + * 185 + * Returns 0 on success, negative value otherwise. 186 + */ 187 + static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r) 188 + { 189 + const char *operation = tomoyo_mkdev_keyword[r->param.mkdev.operation]; 190 + const struct tomoyo_path_info *filename = r->param.mkdev.filename; 191 + const unsigned int major = r->param.mkdev.major; 192 + const unsigned int minor = r->param.mkdev.minor; 193 + const unsigned int mode = r->param.mkdev.mode; 194 + if (r->granted) 195 + return 0; 196 + tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode, 197 + major, minor); 198 + return tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", operation, 199 + tomoyo_pattern(filename), mode, major, minor); 200 + } 201 + 202 + /** 203 + * tomoyo_audit_path_number_log - Audit path/number request log. 204 + * 205 + * @r: Pointer to "struct tomoyo_request_info". 206 + * @error: Error code. 207 + * 208 + * Returns 0 on success, negative value otherwise. 209 + */ 210 + static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r) 211 + { 212 + const u8 type = r->param.path_number.operation; 213 + u8 radix; 214 + const struct tomoyo_path_info *filename = r->param.path_number.filename; 215 + const char *operation = tomoyo_path_number_keyword[type]; 216 + char buffer[64]; 217 + if (r->granted) 218 + return 0; 219 + switch (type) { 220 + case TOMOYO_TYPE_CREATE: 221 + case TOMOYO_TYPE_MKDIR: 222 + case TOMOYO_TYPE_MKFIFO: 223 + case TOMOYO_TYPE_MKSOCK: 224 + case TOMOYO_TYPE_CHMOD: 225 + radix = TOMOYO_VALUE_TYPE_OCTAL; 226 + break; 227 + case TOMOYO_TYPE_IOCTL: 228 + radix = TOMOYO_VALUE_TYPE_HEXADECIMAL; 229 + break; 230 + default: 231 + radix = TOMOYO_VALUE_TYPE_DECIMAL; 232 + break; 233 + } 234 + tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number, 235 + radix); 236 + tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer); 237 + return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, 238 + tomoyo_pattern(filename), buffer); 239 + } 240 + 241 + static bool tomoyo_same_globally_readable(const struct tomoyo_acl_head *a, 242 + const struct tomoyo_acl_head *b) 243 + { 244 + return container_of(a, struct tomoyo_readable_file, 245 + head)->filename == 246 + container_of(b, struct tomoyo_readable_file, 247 + head)->filename; 248 + } 249 + 250 + /** 251 + * tomoyo_update_globally_readable_entry - Update "struct tomoyo_readable_file" list. 216 252 * 217 253 * @filename: Filename unconditionally permitted to open() for reading. 218 254 * @is_delete: True if it is a delete request. ··· 289 195 static int tomoyo_update_globally_readable_entry(const char *filename, 290 196 const bool is_delete) 291 197 { 292 - struct tomoyo_globally_readable_file_entry *ptr; 293 - struct tomoyo_globally_readable_file_entry e = { }; 294 - int error = is_delete ? -ENOENT : -ENOMEM; 198 + struct tomoyo_readable_file e = { }; 199 + int error; 295 200 296 - if (!tomoyo_is_correct_path(filename, 1, 0, -1)) 201 + if (!tomoyo_correct_word(filename)) 297 202 return -EINVAL; 298 203 e.filename = tomoyo_get_name(filename); 299 204 if (!e.filename) 300 205 return -ENOMEM; 301 - if (mutex_lock_interruptible(&tomoyo_policy_lock)) 302 - goto out; 303 - list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { 304 - if (ptr->filename != e.filename) 305 - continue; 306 - ptr->is_deleted = is_delete; 307 - error = 0; 308 - break; 309 - } 310 - if (!is_delete && error) { 311 - struct tomoyo_globally_readable_file_entry *entry = 312 - tomoyo_commit_ok(&e, sizeof(e)); 313 - if (entry) { 314 - list_add_tail_rcu(&entry->list, 315 - &tomoyo_globally_readable_list); 316 - error = 0; 317 - } 318 - } 319 - mutex_unlock(&tomoyo_policy_lock); 320 - out: 206 + error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 207 + &tomoyo_policy_list 208 + [TOMOYO_ID_GLOBALLY_READABLE], 209 + tomoyo_same_globally_readable); 321 210 tomoyo_put_name(e.filename); 322 211 return error; 323 212 } 324 213 325 214 /** 326 - * tomoyo_is_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading. 215 + * tomoyo_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading. 327 216 * 328 217 * @filename: The filename to check. 329 218 * ··· 314 237 * 315 238 * Caller holds tomoyo_read_lock(). 316 239 */ 317 - static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info * 240 + static bool tomoyo_globally_readable_file(const struct tomoyo_path_info * 318 241 filename) 319 242 { 320 - struct tomoyo_globally_readable_file_entry *ptr; 243 + struct tomoyo_readable_file *ptr; 321 244 bool found = false; 322 245 323 - list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { 324 - if (!ptr->is_deleted && 246 + list_for_each_entry_rcu(ptr, &tomoyo_policy_list 247 + [TOMOYO_ID_GLOBALLY_READABLE], head.list) { 248 + if (!ptr->head.is_deleted && 325 249 tomoyo_path_matches_pattern(filename, ptr->filename)) { 326 250 found = true; 327 251 break; ··· 332 254 } 333 255 334 256 /** 335 - * tomoyo_write_globally_readable_policy - Write "struct tomoyo_globally_readable_file_entry" list. 257 + * tomoyo_write_globally_readable - Write "struct tomoyo_readable_file" list. 336 258 * 337 259 * @data: String to parse. 338 260 * @is_delete: True if it is a delete request. ··· 341 263 * 342 264 * Caller holds tomoyo_read_lock(). 343 265 */ 344 - int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) 266 + int tomoyo_write_globally_readable(char *data, const bool is_delete) 345 267 { 346 268 return tomoyo_update_globally_readable_entry(data, is_delete); 347 269 } 348 270 349 - /** 350 - * tomoyo_read_globally_readable_policy - Read "struct tomoyo_globally_readable_file_entry" list. 351 - * 352 - * @head: Pointer to "struct tomoyo_io_buffer". 353 - * 354 - * Returns true on success, false otherwise. 355 - * 356 - * Caller holds tomoyo_read_lock(). 357 - */ 358 - bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) 271 + static bool tomoyo_same_pattern(const struct tomoyo_acl_head *a, 272 + const struct tomoyo_acl_head *b) 359 273 { 360 - struct list_head *pos; 361 - bool done = true; 362 - 363 - list_for_each_cookie(pos, head->read_var2, 364 - &tomoyo_globally_readable_list) { 365 - struct tomoyo_globally_readable_file_entry *ptr; 366 - ptr = list_entry(pos, 367 - struct tomoyo_globally_readable_file_entry, 368 - list); 369 - if (ptr->is_deleted) 370 - continue; 371 - done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALLOW_READ "%s\n", 372 - ptr->filename->name); 373 - if (!done) 374 - break; 375 - } 376 - return done; 274 + return container_of(a, struct tomoyo_no_pattern, head)->pattern == 275 + container_of(b, struct tomoyo_no_pattern, head)->pattern; 377 276 } 378 277 379 - /* tomoyo_pattern_list is used for holding list of pathnames which are used for 380 - * converting pathnames to pathname patterns during learning mode. 381 - * 382 - * An entry is added by 383 - * 384 - * # echo 'file_pattern /proc/\$/mounts' > \ 385 - * /sys/kernel/security/tomoyo/exception_policy 386 - * 387 - * and is deleted by 388 - * 389 - * # echo 'delete file_pattern /proc/\$/mounts' > \ 390 - * /sys/kernel/security/tomoyo/exception_policy 391 - * 392 - * and all entries are retrieved by 393 - * 394 - * # grep ^file_pattern /sys/kernel/security/tomoyo/exception_policy 395 - * 396 - * In the example above, if a process which belongs to a domain which is in 397 - * learning mode requested open("/proc/1/mounts", O_RDONLY), 398 - * "allow_read /proc/\$/mounts" is automatically added to the domain which that 399 - * process belongs to. 400 - * 401 - * It is not a desirable behavior that we have to use /proc/\$/ instead of 402 - * /proc/self/ when current process needs to access only current process's 403 - * information. As of now, LSM version of TOMOYO is using __d_path() for 404 - * calculating pathname. Non LSM version of TOMOYO is using its own function 405 - * which pretends as if /proc/self/ is not a symlink; so that we can forbid 406 - * current process from accessing other process's information. 407 - */ 408 - LIST_HEAD(tomoyo_pattern_list); 409 - 410 278 /** 411 - * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list. 279 + * tomoyo_update_file_pattern_entry - Update "struct tomoyo_no_pattern" list. 412 280 * 413 281 * @pattern: Pathname pattern. 414 282 * @is_delete: True if it is a delete request. ··· 366 342 static int tomoyo_update_file_pattern_entry(const char *pattern, 367 343 const bool is_delete) 368 344 { 369 - struct tomoyo_pattern_entry *ptr; 370 - struct tomoyo_pattern_entry e = { .pattern = tomoyo_get_name(pattern) }; 371 - int error = is_delete ? -ENOENT : -ENOMEM; 345 + struct tomoyo_no_pattern e = { }; 346 + int error; 372 347 348 + if (!tomoyo_correct_word(pattern)) 349 + return -EINVAL; 350 + e.pattern = tomoyo_get_name(pattern); 373 351 if (!e.pattern) 374 - return error; 375 - if (!e.pattern->is_patterned) 376 - goto out; 377 - if (mutex_lock_interruptible(&tomoyo_policy_lock)) 378 - goto out; 379 - list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { 380 - if (e.pattern != ptr->pattern) 381 - continue; 382 - ptr->is_deleted = is_delete; 383 - error = 0; 384 - break; 385 - } 386 - if (!is_delete && error) { 387 - struct tomoyo_pattern_entry *entry = 388 - tomoyo_commit_ok(&e, sizeof(e)); 389 - if (entry) { 390 - list_add_tail_rcu(&entry->list, &tomoyo_pattern_list); 391 - error = 0; 392 - } 393 - } 394 - mutex_unlock(&tomoyo_policy_lock); 395 - out: 352 + return -ENOMEM; 353 + error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 354 + &tomoyo_policy_list[TOMOYO_ID_PATTERN], 355 + tomoyo_same_pattern); 396 356 tomoyo_put_name(e.pattern); 397 357 return error; 398 358 } 399 359 400 360 /** 401 - * tomoyo_get_file_pattern - Get patterned pathname. 361 + * tomoyo_pattern - Get patterned pathname. 402 362 * 403 363 * @filename: The filename to find patterned pathname. 404 364 * ··· 390 382 * 391 383 * Caller holds tomoyo_read_lock(). 392 384 */ 393 - static const struct tomoyo_path_info * 394 - tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) 385 + const char *tomoyo_pattern(const struct tomoyo_path_info *filename) 395 386 { 396 - struct tomoyo_pattern_entry *ptr; 387 + struct tomoyo_no_pattern *ptr; 397 388 const struct tomoyo_path_info *pattern = NULL; 398 389 399 - list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { 400 - if (ptr->is_deleted) 390 + list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_PATTERN], 391 + head.list) { 392 + if (ptr->head.is_deleted) 401 393 continue; 402 394 if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) 403 395 continue; ··· 411 403 } 412 404 if (pattern) 413 405 filename = pattern; 414 - return filename; 406 + return filename->name; 415 407 } 416 408 417 409 /** 418 - * tomoyo_write_pattern_policy - Write "struct tomoyo_pattern_entry" list. 410 + * tomoyo_write_pattern - Write "struct tomoyo_no_pattern" list. 419 411 * 420 412 * @data: String to parse. 421 413 * @is_delete: True if it is a delete request. ··· 424 416 * 425 417 * Caller holds tomoyo_read_lock(). 426 418 */ 427 - int tomoyo_write_pattern_policy(char *data, const bool is_delete) 419 + int tomoyo_write_pattern(char *data, const bool is_delete) 428 420 { 429 421 return tomoyo_update_file_pattern_entry(data, is_delete); 430 422 } 431 423 432 - /** 433 - * tomoyo_read_file_pattern - Read "struct tomoyo_pattern_entry" list. 434 - * 435 - * @head: Pointer to "struct tomoyo_io_buffer". 436 - * 437 - * Returns true on success, false otherwise. 438 - * 439 - * Caller holds tomoyo_read_lock(). 440 - */ 441 - bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) 424 + static bool tomoyo_same_no_rewrite(const struct tomoyo_acl_head *a, 425 + const struct tomoyo_acl_head *b) 442 426 { 443 - struct list_head *pos; 444 - bool done = true; 445 - 446 - list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) { 447 - struct tomoyo_pattern_entry *ptr; 448 - ptr = list_entry(pos, struct tomoyo_pattern_entry, list); 449 - if (ptr->is_deleted) 450 - continue; 451 - done = tomoyo_io_printf(head, TOMOYO_KEYWORD_FILE_PATTERN 452 - "%s\n", ptr->pattern->name); 453 - if (!done) 454 - break; 455 - } 456 - return done; 427 + return container_of(a, struct tomoyo_no_rewrite, head)->pattern 428 + == container_of(b, struct tomoyo_no_rewrite, head) 429 + ->pattern; 457 430 } 458 431 459 - /* 460 - * tomoyo_no_rewrite_list is used for holding list of pathnames which are by 461 - * default forbidden to modify already written content of a file. 462 - * 463 - * An entry is added by 464 - * 465 - * # echo 'deny_rewrite /var/log/messages' > \ 466 - * /sys/kernel/security/tomoyo/exception_policy 467 - * 468 - * and is deleted by 469 - * 470 - * # echo 'delete deny_rewrite /var/log/messages' > \ 471 - * /sys/kernel/security/tomoyo/exception_policy 472 - * 473 - * and all entries are retrieved by 474 - * 475 - * # grep ^deny_rewrite /sys/kernel/security/tomoyo/exception_policy 476 - * 477 - * In the example above, if a process requested to rewrite /var/log/messages , 478 - * the process can't rewrite unless the domain which that process belongs to 479 - * has "allow_rewrite /var/log/messages" entry. 480 - * 481 - * It is not a desirable behavior that we have to add "\040(deleted)" suffix 482 - * when we want to allow rewriting already unlink()ed file. As of now, 483 - * LSM version of TOMOYO is using __d_path() for calculating pathname. 484 - * Non LSM version of TOMOYO is using its own function which doesn't append 485 - * " (deleted)" suffix if the file is already unlink()ed; so that we don't 486 - * need to worry whether the file is already unlink()ed or not. 487 - */ 488 - LIST_HEAD(tomoyo_no_rewrite_list); 489 - 490 432 /** 491 - * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list. 433 + * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite" list. 492 434 * 493 435 * @pattern: Pathname pattern that are not rewritable by default. 494 436 * @is_delete: True if it is a delete request. ··· 450 492 static int tomoyo_update_no_rewrite_entry(const char *pattern, 451 493 const bool is_delete) 452 494 { 453 - struct tomoyo_no_rewrite_entry *ptr; 454 - struct tomoyo_no_rewrite_entry e = { }; 455 - int error = is_delete ? -ENOENT : -ENOMEM; 495 + struct tomoyo_no_rewrite e = { }; 496 + int error; 456 497 457 - if (!tomoyo_is_correct_path(pattern, 0, 0, 0)) 498 + if (!tomoyo_correct_word(pattern)) 458 499 return -EINVAL; 459 500 e.pattern = tomoyo_get_name(pattern); 460 501 if (!e.pattern) 461 - return error; 462 - if (mutex_lock_interruptible(&tomoyo_policy_lock)) 463 - goto out; 464 - list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { 465 - if (ptr->pattern != e.pattern) 466 - continue; 467 - ptr->is_deleted = is_delete; 468 - error = 0; 469 - break; 470 - } 471 - if (!is_delete && error) { 472 - struct tomoyo_no_rewrite_entry *entry = 473 - tomoyo_commit_ok(&e, sizeof(e)); 474 - if (entry) { 475 - list_add_tail_rcu(&entry->list, 476 - &tomoyo_no_rewrite_list); 477 - error = 0; 478 - } 479 - } 480 - mutex_unlock(&tomoyo_policy_lock); 481 - out: 502 + return -ENOMEM; 503 + error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 504 + &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE], 505 + tomoyo_same_no_rewrite); 482 506 tomoyo_put_name(e.pattern); 483 507 return error; 484 508 } 485 509 486 510 /** 487 - * tomoyo_is_no_rewrite_file - Check if the given pathname is not permitted to be rewrited. 511 + * tomoyo_no_rewrite_file - Check if the given pathname is not permitted to be rewrited. 488 512 * 489 513 * @filename: Filename to check. 490 514 * ··· 475 535 * 476 536 * Caller holds tomoyo_read_lock(). 477 537 */ 478 - static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) 538 + static bool tomoyo_no_rewrite_file(const struct tomoyo_path_info *filename) 479 539 { 480 - struct tomoyo_no_rewrite_entry *ptr; 540 + struct tomoyo_no_rewrite *ptr; 481 541 bool found = false; 482 542 483 - list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { 484 - if (ptr->is_deleted) 543 + list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE], 544 + head.list) { 545 + if (ptr->head.is_deleted) 485 546 continue; 486 547 if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) 487 548 continue; ··· 493 552 } 494 553 495 554 /** 496 - * tomoyo_write_no_rewrite_policy - Write "struct tomoyo_no_rewrite_entry" list. 555 + * tomoyo_write_no_rewrite - Write "struct tomoyo_no_rewrite" list. 497 556 * 498 557 * @data: String to parse. 499 558 * @is_delete: True if it is a delete request. ··· 502 561 * 503 562 * Caller holds tomoyo_read_lock(). 504 563 */ 505 - int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete) 564 + int tomoyo_write_no_rewrite(char *data, const bool is_delete) 506 565 { 507 566 return tomoyo_update_no_rewrite_entry(data, is_delete); 508 567 } 509 568 510 - /** 511 - * tomoyo_read_no_rewrite_policy - Read "struct tomoyo_no_rewrite_entry" list. 512 - * 513 - * @head: Pointer to "struct tomoyo_io_buffer". 514 - * 515 - * Returns true on success, false otherwise. 516 - * 517 - * Caller holds tomoyo_read_lock(). 518 - */ 519 - bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) 569 + static bool tomoyo_check_path_acl(struct tomoyo_request_info *r, 570 + const struct tomoyo_acl_info *ptr) 520 571 { 521 - struct list_head *pos; 522 - bool done = true; 523 - 524 - list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) { 525 - struct tomoyo_no_rewrite_entry *ptr; 526 - ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list); 527 - if (ptr->is_deleted) 528 - continue; 529 - done = tomoyo_io_printf(head, TOMOYO_KEYWORD_DENY_REWRITE 530 - "%s\n", ptr->pattern->name); 531 - if (!done) 532 - break; 572 + const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl), 573 + head); 574 + if (acl->perm & (1 << r->param.path.operation)) { 575 + r->param.path.matched_path = 576 + tomoyo_compare_name_union(r->param.path.filename, 577 + &acl->name); 578 + return r->param.path.matched_path != NULL; 533 579 } 534 - return done; 580 + return false; 535 581 } 536 582 537 - /** 538 - * tomoyo_update_file_acl - Update file's read/write/execute ACL. 539 - * 540 - * @filename: Filename. 541 - * @perm: Permission (between 1 to 7). 542 - * @domain: Pointer to "struct tomoyo_domain_info". 543 - * @is_delete: True if it is a delete request. 544 - * 545 - * Returns 0 on success, negative value otherwise. 546 - * 547 - * This is legacy support interface for older policy syntax. 548 - * Current policy syntax uses "allow_read/write" instead of "6", 549 - * "allow_read" instead of "4", "allow_write" instead of "2", 550 - * "allow_execute" instead of "1". 551 - * 552 - * Caller holds tomoyo_read_lock(). 553 - */ 554 - static int tomoyo_update_file_acl(const char *filename, u8 perm, 555 - struct tomoyo_domain_info * const domain, 583 + static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r, 584 + const struct tomoyo_acl_info *ptr) 585 + { 586 + const struct tomoyo_path_number_acl *acl = 587 + container_of(ptr, typeof(*acl), head); 588 + return (acl->perm & (1 << r->param.path_number.operation)) && 589 + tomoyo_compare_number_union(r->param.path_number.number, 590 + &acl->number) && 591 + tomoyo_compare_name_union(r->param.path_number.filename, 592 + &acl->name); 593 + } 594 + 595 + static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r, 596 + const struct tomoyo_acl_info *ptr) 597 + { 598 + const struct tomoyo_path2_acl *acl = 599 + container_of(ptr, typeof(*acl), head); 600 + return (acl->perm & (1 << r->param.path2.operation)) && 601 + tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1) 602 + && tomoyo_compare_name_union(r->param.path2.filename2, 603 + &acl->name2); 604 + } 605 + 606 + static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r, 607 + const struct tomoyo_acl_info *ptr) 608 + { 609 + const struct tomoyo_mkdev_acl *acl = 610 + container_of(ptr, typeof(*acl), head); 611 + return (acl->perm & (1 << r->param.mkdev.operation)) && 612 + tomoyo_compare_number_union(r->param.mkdev.mode, 613 + &acl->mode) && 614 + tomoyo_compare_number_union(r->param.mkdev.major, 615 + &acl->major) && 616 + tomoyo_compare_number_union(r->param.mkdev.minor, 617 + &acl->minor) && 618 + tomoyo_compare_name_union(r->param.mkdev.filename, 619 + &acl->name); 620 + } 621 + 622 + static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a, 623 + const struct tomoyo_acl_info *b) 624 + { 625 + const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head); 626 + const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head); 627 + return tomoyo_same_acl_head(&p1->head, &p2->head) && 628 + tomoyo_same_name_union(&p1->name, &p2->name); 629 + } 630 + 631 + static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a, 632 + struct tomoyo_acl_info *b, 556 633 const bool is_delete) 557 634 { 558 - if (perm > 7 || !perm) { 559 - printk(KERN_DEBUG "%s: Invalid permission '%d %s'\n", 560 - __func__, perm, filename); 561 - return -EINVAL; 635 + u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head) 636 + ->perm; 637 + u16 perm = *a_perm; 638 + const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm; 639 + if (is_delete) { 640 + perm &= ~b_perm; 641 + if ((perm & TOMOYO_RW_MASK) != TOMOYO_RW_MASK) 642 + perm &= ~(1 << TOMOYO_TYPE_READ_WRITE); 643 + else if (!(perm & (1 << TOMOYO_TYPE_READ_WRITE))) 644 + perm &= ~TOMOYO_RW_MASK; 645 + } else { 646 + perm |= b_perm; 647 + if ((perm & TOMOYO_RW_MASK) == TOMOYO_RW_MASK) 648 + perm |= (1 << TOMOYO_TYPE_READ_WRITE); 649 + else if (perm & (1 << TOMOYO_TYPE_READ_WRITE)) 650 + perm |= TOMOYO_RW_MASK; 562 651 } 563 - if (filename[0] != '@' && tomoyo_strendswith(filename, "/")) 564 - /* 565 - * Only 'allow_mkdir' and 'allow_rmdir' are valid for 566 - * directory permissions. 567 - */ 568 - return 0; 569 - if (perm & 4) 570 - tomoyo_update_path_acl(TOMOYO_TYPE_READ, filename, domain, 571 - is_delete); 572 - if (perm & 2) 573 - tomoyo_update_path_acl(TOMOYO_TYPE_WRITE, filename, domain, 574 - is_delete); 575 - if (perm & 1) 576 - tomoyo_update_path_acl(TOMOYO_TYPE_EXECUTE, filename, domain, 577 - is_delete); 578 - return 0; 579 - } 580 - 581 - /** 582 - * tomoyo_path_acl2 - Check permission for single path operation. 583 - * 584 - * @domain: Pointer to "struct tomoyo_domain_info". 585 - * @filename: Filename to check. 586 - * @perm: Permission. 587 - * @may_use_pattern: True if patterned ACL is permitted. 588 - * 589 - * Returns 0 on success, -EPERM otherwise. 590 - * 591 - * Caller holds tomoyo_read_lock(). 592 - */ 593 - static int tomoyo_path_acl2(const struct tomoyo_domain_info *domain, 594 - const struct tomoyo_path_info *filename, 595 - const u32 perm, const bool may_use_pattern) 596 - { 597 - struct tomoyo_acl_info *ptr; 598 - int error = -EPERM; 599 - 600 - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 601 - struct tomoyo_path_acl *acl; 602 - if (ptr->type != TOMOYO_TYPE_PATH_ACL) 603 - continue; 604 - acl = container_of(ptr, struct tomoyo_path_acl, head); 605 - if (perm <= 0xFFFF) { 606 - if (!(acl->perm & perm)) 607 - continue; 608 - } else { 609 - if (!(acl->perm_high & (perm >> 16))) 610 - continue; 611 - } 612 - if (!tomoyo_compare_name_union_pattern(filename, &acl->name, 613 - may_use_pattern)) 614 - continue; 615 - error = 0; 616 - break; 617 - } 618 - return error; 619 - } 620 - 621 - /** 622 - * tomoyo_check_file_acl - Check permission for opening files. 623 - * 624 - * @domain: Pointer to "struct tomoyo_domain_info". 625 - * @filename: Filename to check. 626 - * @operation: Mode ("read" or "write" or "read/write" or "execute"). 627 - * 628 - * Returns 0 on success, -EPERM otherwise. 629 - * 630 - * Caller holds tomoyo_read_lock(). 631 - */ 632 - static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain, 633 - const struct tomoyo_path_info *filename, 634 - const u8 operation) 635 - { 636 - u32 perm = 0; 637 - 638 - if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) 639 - return 0; 640 - if (operation == 6) 641 - perm = 1 << TOMOYO_TYPE_READ_WRITE; 642 - else if (operation == 4) 643 - perm = 1 << TOMOYO_TYPE_READ; 644 - else if (operation == 2) 645 - perm = 1 << TOMOYO_TYPE_WRITE; 646 - else if (operation == 1) 647 - perm = 1 << TOMOYO_TYPE_EXECUTE; 648 - else 649 - BUG(); 650 - return tomoyo_path_acl2(domain, filename, perm, operation != 1); 651 - } 652 - 653 - /** 654 - * tomoyo_check_file_perm2 - Check permission for opening files. 655 - * 656 - * @domain: Pointer to "struct tomoyo_domain_info". 657 - * @filename: Filename to check. 658 - * @perm: Mode ("read" or "write" or "read/write" or "execute"). 659 - * @operation: Operation name passed used for verbose mode. 660 - * @mode: Access control mode. 661 - * 662 - * Returns 0 on success, negative value otherwise. 663 - * 664 - * Caller holds tomoyo_read_lock(). 665 - */ 666 - static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, 667 - const struct tomoyo_path_info *filename, 668 - const u8 perm, const char *operation, 669 - const u8 mode) 670 - { 671 - const bool is_enforce = (mode == 3); 672 - const char *msg = "<unknown>"; 673 - int error = 0; 674 - 675 - if (!filename) 676 - return 0; 677 - error = tomoyo_check_file_acl(domain, filename, perm); 678 - if (error && perm == 4 && !domain->ignore_global_allow_read 679 - && tomoyo_is_globally_readable_file(filename)) 680 - error = 0; 681 - if (perm == 6) 682 - msg = tomoyo_path2keyword(TOMOYO_TYPE_READ_WRITE); 683 - else if (perm == 4) 684 - msg = tomoyo_path2keyword(TOMOYO_TYPE_READ); 685 - else if (perm == 2) 686 - msg = tomoyo_path2keyword(TOMOYO_TYPE_WRITE); 687 - else if (perm == 1) 688 - msg = tomoyo_path2keyword(TOMOYO_TYPE_EXECUTE); 689 - else 690 - BUG(); 691 - if (!error) 692 - return 0; 693 - if (tomoyo_verbose_mode(domain)) 694 - printk(KERN_WARNING "TOMOYO-%s: Access '%s(%s) %s' denied " 695 - "for %s\n", tomoyo_get_msg(is_enforce), msg, operation, 696 - filename->name, tomoyo_get_last_name(domain)); 697 - if (is_enforce) 698 - return error; 699 - if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { 700 - /* Don't use patterns for execute permission. */ 701 - const struct tomoyo_path_info *patterned_file = (perm != 1) ? 702 - tomoyo_get_file_pattern(filename) : filename; 703 - tomoyo_update_file_acl(patterned_file->name, perm, 704 - domain, false); 705 - } 706 - return 0; 707 - } 708 - 709 - /** 710 - * tomoyo_write_file_policy - Update file related list. 711 - * 712 - * @data: String to parse. 713 - * @domain: Pointer to "struct tomoyo_domain_info". 714 - * @is_delete: True if it is a delete request. 715 - * 716 - * Returns 0 on success, negative value otherwise. 717 - * 718 - * Caller holds tomoyo_read_lock(). 719 - */ 720 - int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, 721 - const bool is_delete) 722 - { 723 - char *filename = strchr(data, ' '); 724 - char *filename2; 725 - unsigned int perm; 726 - u8 type; 727 - 728 - if (!filename) 729 - return -EINVAL; 730 - *filename++ = '\0'; 731 - if (sscanf(data, "%u", &perm) == 1) 732 - return tomoyo_update_file_acl(filename, (u8) perm, domain, 733 - is_delete); 734 - if (strncmp(data, "allow_", 6)) 735 - goto out; 736 - data += 6; 737 - for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) { 738 - if (strcmp(data, tomoyo_path_keyword[type])) 739 - continue; 740 - return tomoyo_update_path_acl(type, filename, domain, 741 - is_delete); 742 - } 743 - filename2 = strchr(filename, ' '); 744 - if (!filename2) 745 - goto out; 746 - *filename2++ = '\0'; 747 - for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) { 748 - if (strcmp(data, tomoyo_path2_keyword[type])) 749 - continue; 750 - return tomoyo_update_path2_acl(type, filename, filename2, 751 - domain, is_delete); 752 - } 753 - out: 754 - return -EINVAL; 652 + *a_perm = perm; 653 + return !perm; 755 654 } 756 655 757 656 /** ··· 607 826 * Caller holds tomoyo_read_lock(). 608 827 */ 609 828 static int tomoyo_update_path_acl(const u8 type, const char *filename, 610 - struct tomoyo_domain_info *const domain, 829 + struct tomoyo_domain_info * const domain, 611 830 const bool is_delete) 612 831 { 613 - static const u32 tomoyo_rw_mask = 614 - (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE); 615 - const u32 perm = 1 << type; 616 - struct tomoyo_acl_info *ptr; 617 832 struct tomoyo_path_acl e = { 618 833 .head.type = TOMOYO_TYPE_PATH_ACL, 619 - .perm_high = perm >> 16, 620 - .perm = perm 834 + .perm = 1 << type 621 835 }; 622 - int error = is_delete ? -ENOENT : -ENOMEM; 623 - 624 - if (type == TOMOYO_TYPE_READ_WRITE) 625 - e.perm |= tomoyo_rw_mask; 626 - if (!domain) 627 - return -EINVAL; 836 + int error; 837 + if (e.perm == (1 << TOMOYO_TYPE_READ_WRITE)) 838 + e.perm |= TOMOYO_RW_MASK; 628 839 if (!tomoyo_parse_name_union(filename, &e.name)) 629 840 return -EINVAL; 630 - if (mutex_lock_interruptible(&tomoyo_policy_lock)) 631 - goto out; 632 - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 633 - struct tomoyo_path_acl *acl = 634 - container_of(ptr, struct tomoyo_path_acl, head); 635 - if (!tomoyo_is_same_path_acl(acl, &e)) 636 - continue; 637 - if (is_delete) { 638 - if (perm <= 0xFFFF) 639 - acl->perm &= ~perm; 640 - else 641 - acl->perm_high &= ~(perm >> 16); 642 - if ((acl->perm & tomoyo_rw_mask) != tomoyo_rw_mask) 643 - acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE); 644 - else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))) 645 - acl->perm &= ~tomoyo_rw_mask; 646 - } else { 647 - if (perm <= 0xFFFF) 648 - acl->perm |= perm; 649 - else 650 - acl->perm_high |= (perm >> 16); 651 - if ((acl->perm & tomoyo_rw_mask) == tomoyo_rw_mask) 652 - acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE; 653 - else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)) 654 - acl->perm |= tomoyo_rw_mask; 655 - } 656 - error = 0; 657 - break; 658 - } 659 - if (!is_delete && error) { 660 - struct tomoyo_path_acl *entry = 661 - tomoyo_commit_ok(&e, sizeof(e)); 662 - if (entry) { 663 - list_add_tail_rcu(&entry->head.list, 664 - &domain->acl_info_list); 665 - error = 0; 666 - } 667 - } 668 - mutex_unlock(&tomoyo_policy_lock); 669 - out: 841 + error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, 842 + tomoyo_same_path_acl, 843 + tomoyo_merge_path_acl); 670 844 tomoyo_put_name_union(&e.name); 671 845 return error; 846 + } 847 + 848 + static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a, 849 + const struct tomoyo_acl_info *b) 850 + { 851 + const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), 852 + head); 853 + const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), 854 + head); 855 + return tomoyo_same_acl_head(&p1->head, &p2->head) 856 + && tomoyo_same_name_union(&p1->name, &p2->name) 857 + && tomoyo_same_number_union(&p1->mode, &p2->mode) 858 + && tomoyo_same_number_union(&p1->major, &p2->major) 859 + && tomoyo_same_number_union(&p1->minor, &p2->minor); 860 + } 861 + 862 + static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a, 863 + struct tomoyo_acl_info *b, 864 + const bool is_delete) 865 + { 866 + u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl, 867 + head)->perm; 868 + u8 perm = *a_perm; 869 + const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head) 870 + ->perm; 871 + if (is_delete) 872 + perm &= ~b_perm; 873 + else 874 + perm |= b_perm; 875 + *a_perm = perm; 876 + return !perm; 877 + } 878 + 879 + /** 880 + * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list. 881 + * 882 + * @type: Type of operation. 883 + * @filename: Filename. 884 + * @mode: Create mode. 885 + * @major: Device major number. 886 + * @minor: Device minor number. 887 + * @domain: Pointer to "struct tomoyo_domain_info". 888 + * @is_delete: True if it is a delete request. 889 + * 890 + * Returns 0 on success, negative value otherwise. 891 + * 892 + * Caller holds tomoyo_read_lock(). 893 + */ 894 + static int tomoyo_update_mkdev_acl(const u8 type, const char *filename, 895 + char *mode, char *major, char *minor, 896 + struct tomoyo_domain_info * const 897 + domain, const bool is_delete) 898 + { 899 + struct tomoyo_mkdev_acl e = { 900 + .head.type = TOMOYO_TYPE_MKDEV_ACL, 901 + .perm = 1 << type 902 + }; 903 + int error = is_delete ? -ENOENT : -ENOMEM; 904 + if (!tomoyo_parse_name_union(filename, &e.name) || 905 + !tomoyo_parse_number_union(mode, &e.mode) || 906 + !tomoyo_parse_number_union(major, &e.major) || 907 + !tomoyo_parse_number_union(minor, &e.minor)) 908 + goto out; 909 + error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, 910 + tomoyo_same_mkdev_acl, 911 + tomoyo_merge_mkdev_acl); 912 + out: 913 + tomoyo_put_name_union(&e.name); 914 + tomoyo_put_number_union(&e.mode); 915 + tomoyo_put_number_union(&e.major); 916 + tomoyo_put_number_union(&e.minor); 917 + return error; 918 + } 919 + 920 + static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a, 921 + const struct tomoyo_acl_info *b) 922 + { 923 + const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head); 924 + const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head); 925 + return tomoyo_same_acl_head(&p1->head, &p2->head) 926 + && tomoyo_same_name_union(&p1->name1, &p2->name1) 927 + && tomoyo_same_name_union(&p1->name2, &p2->name2); 928 + } 929 + 930 + static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a, 931 + struct tomoyo_acl_info *b, 932 + const bool is_delete) 933 + { 934 + u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head) 935 + ->perm; 936 + u8 perm = *a_perm; 937 + const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm; 938 + if (is_delete) 939 + perm &= ~b_perm; 940 + else 941 + perm |= b_perm; 942 + *a_perm = perm; 943 + return !perm; 672 944 } 673 945 674 946 /** ··· 739 905 */ 740 906 static int tomoyo_update_path2_acl(const u8 type, const char *filename1, 741 907 const char *filename2, 742 - struct tomoyo_domain_info *const domain, 908 + struct tomoyo_domain_info * const domain, 743 909 const bool is_delete) 744 910 { 745 - const u8 perm = 1 << type; 746 911 struct tomoyo_path2_acl e = { 747 912 .head.type = TOMOYO_TYPE_PATH2_ACL, 748 - .perm = perm 913 + .perm = 1 << type 749 914 }; 750 - struct tomoyo_acl_info *ptr; 751 915 int error = is_delete ? -ENOENT : -ENOMEM; 752 - 753 - if (!domain) 754 - return -EINVAL; 755 916 if (!tomoyo_parse_name_union(filename1, &e.name1) || 756 917 !tomoyo_parse_name_union(filename2, &e.name2)) 757 918 goto out; 758 - if (mutex_lock_interruptible(&tomoyo_policy_lock)) 759 - goto out; 760 - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 761 - struct tomoyo_path2_acl *acl = 762 - container_of(ptr, struct tomoyo_path2_acl, head); 763 - if (!tomoyo_is_same_path2_acl(acl, &e)) 764 - continue; 765 - if (is_delete) 766 - acl->perm &= ~perm; 767 - else 768 - acl->perm |= perm; 769 - error = 0; 770 - break; 771 - } 772 - if (!is_delete && error) { 773 - struct tomoyo_path2_acl *entry = 774 - tomoyo_commit_ok(&e, sizeof(e)); 775 - if (entry) { 776 - list_add_tail_rcu(&entry->head.list, 777 - &domain->acl_info_list); 778 - error = 0; 779 - } 780 - } 781 - mutex_unlock(&tomoyo_policy_lock); 919 + error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, 920 + tomoyo_same_path2_acl, 921 + tomoyo_merge_path2_acl); 782 922 out: 783 923 tomoyo_put_name_union(&e.name1); 784 924 tomoyo_put_name_union(&e.name2); ··· 760 952 } 761 953 762 954 /** 763 - * tomoyo_path_acl - Check permission for single path operation. 955 + * tomoyo_path_permission - Check permission for single path operation. 764 956 * 765 - * @domain: Pointer to "struct tomoyo_domain_info". 766 - * @type: Type of operation. 767 - * @filename: Filename to check. 768 - * 769 - * Returns 0 on success, negative value otherwise. 770 - * 771 - * Caller holds tomoyo_read_lock(). 772 - */ 773 - static int tomoyo_path_acl(struct tomoyo_domain_info *domain, const u8 type, 774 - const struct tomoyo_path_info *filename) 775 - { 776 - if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) 777 - return 0; 778 - return tomoyo_path_acl2(domain, filename, 1 << type, 1); 779 - } 780 - 781 - /** 782 - * tomoyo_path2_acl - Check permission for double path operation. 783 - * 784 - * @domain: Pointer to "struct tomoyo_domain_info". 785 - * @type: Type of operation. 786 - * @filename1: First filename to check. 787 - * @filename2: Second filename to check. 788 - * 789 - * Returns 0 on success, -EPERM otherwise. 790 - * 791 - * Caller holds tomoyo_read_lock(). 792 - */ 793 - static int tomoyo_path2_acl(const struct tomoyo_domain_info *domain, 794 - const u8 type, 795 - const struct tomoyo_path_info *filename1, 796 - const struct tomoyo_path_info *filename2) 797 - { 798 - struct tomoyo_acl_info *ptr; 799 - const u8 perm = 1 << type; 800 - int error = -EPERM; 801 - 802 - if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) 803 - return 0; 804 - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 805 - struct tomoyo_path2_acl *acl; 806 - if (ptr->type != TOMOYO_TYPE_PATH2_ACL) 807 - continue; 808 - acl = container_of(ptr, struct tomoyo_path2_acl, head); 809 - if (!(acl->perm & perm)) 810 - continue; 811 - if (!tomoyo_compare_name_union(filename1, &acl->name1)) 812 - continue; 813 - if (!tomoyo_compare_name_union(filename2, &acl->name2)) 814 - continue; 815 - error = 0; 816 - break; 817 - } 818 - return error; 819 - } 820 - 821 - /** 822 - * tomoyo_path_permission2 - Check permission for single path operation. 823 - * 824 - * @domain: Pointer to "struct tomoyo_domain_info". 957 + * @r: Pointer to "struct tomoyo_request_info". 825 958 * @operation: Type of operation. 826 959 * @filename: Filename to check. 827 - * @mode: Access control mode. 828 960 * 829 961 * Returns 0 on success, negative value otherwise. 830 962 * 831 963 * Caller holds tomoyo_read_lock(). 832 964 */ 833 - static int tomoyo_path_permission2(struct tomoyo_domain_info *const domain, 834 - u8 operation, 835 - const struct tomoyo_path_info *filename, 836 - const u8 mode) 965 + int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, 966 + const struct tomoyo_path_info *filename) 837 967 { 838 - const char *msg; 839 968 int error; 840 - const bool is_enforce = (mode == 3); 841 969 842 - if (!mode) 843 - return 0; 844 970 next: 845 - error = tomoyo_path_acl(domain, operation, filename); 846 - msg = tomoyo_path2keyword(operation); 847 - if (!error) 848 - goto ok; 849 - if (tomoyo_verbose_mode(domain)) 850 - printk(KERN_WARNING "TOMOYO-%s: Access '%s %s' denied for %s\n", 851 - tomoyo_get_msg(is_enforce), msg, filename->name, 852 - tomoyo_get_last_name(domain)); 853 - if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { 854 - const char *name = tomoyo_get_file_pattern(filename)->name; 855 - tomoyo_update_path_acl(operation, name, domain, false); 856 - } 857 - if (!is_enforce) 858 - error = 0; 859 - ok: 971 + r->type = tomoyo_p2mac[operation]; 972 + r->mode = tomoyo_get_mode(r->profile, r->type); 973 + if (r->mode == TOMOYO_CONFIG_DISABLED) 974 + return 0; 975 + r->param_type = TOMOYO_TYPE_PATH_ACL; 976 + r->param.path.filename = filename; 977 + r->param.path.operation = operation; 978 + do { 979 + tomoyo_check_acl(r, tomoyo_check_path_acl); 980 + if (!r->granted && operation == TOMOYO_TYPE_READ && 981 + !r->domain->ignore_global_allow_read && 982 + tomoyo_globally_readable_file(filename)) 983 + r->granted = true; 984 + error = tomoyo_audit_path_log(r); 985 + /* 986 + * Do not retry for execute request, for alias may have 987 + * changed. 988 + */ 989 + } while (error == TOMOYO_RETRY_REQUEST && 990 + operation != TOMOYO_TYPE_EXECUTE); 860 991 /* 861 992 * Since "allow_truncate" doesn't imply "allow_rewrite" permission, 862 993 * we need to check "allow_rewrite" permission if the filename is 863 994 * specified by "deny_rewrite" keyword. 864 995 */ 865 996 if (!error && operation == TOMOYO_TYPE_TRUNCATE && 866 - tomoyo_is_no_rewrite_file(filename)) { 997 + tomoyo_no_rewrite_file(filename)) { 867 998 operation = TOMOYO_TYPE_REWRITE; 868 999 goto next; 869 1000 } 870 1001 return error; 871 1002 } 872 1003 873 - /** 874 - * tomoyo_check_exec_perm - Check permission for "execute". 875 - * 876 - * @domain: Pointer to "struct tomoyo_domain_info". 877 - * @filename: Check permission for "execute". 878 - * 879 - * Returns 0 on success, negativevalue otherwise. 880 - * 881 - * Caller holds tomoyo_read_lock(). 882 - */ 883 - int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, 884 - const struct tomoyo_path_info *filename) 1004 + static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a, 1005 + const struct tomoyo_acl_info *b) 885 1006 { 886 - const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); 1007 + const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1), 1008 + head); 1009 + const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2), 1010 + head); 1011 + return tomoyo_same_acl_head(&p1->head, &p2->head) 1012 + && tomoyo_same_name_union(&p1->name, &p2->name) 1013 + && tomoyo_same_number_union(&p1->number, &p2->number); 1014 + } 887 1015 888 - if (!mode) 1016 + static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a, 1017 + struct tomoyo_acl_info *b, 1018 + const bool is_delete) 1019 + { 1020 + u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl, 1021 + head)->perm; 1022 + u8 perm = *a_perm; 1023 + const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head) 1024 + ->perm; 1025 + if (is_delete) 1026 + perm &= ~b_perm; 1027 + else 1028 + perm |= b_perm; 1029 + *a_perm = perm; 1030 + return !perm; 1031 + } 1032 + 1033 + /** 1034 + * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL. 1035 + * 1036 + * @type: Type of operation. 1037 + * @filename: Filename. 1038 + * @number: Number. 1039 + * @domain: Pointer to "struct tomoyo_domain_info". 1040 + * @is_delete: True if it is a delete request. 1041 + * 1042 + * Returns 0 on success, negative value otherwise. 1043 + */ 1044 + static int tomoyo_update_path_number_acl(const u8 type, const char *filename, 1045 + char *number, 1046 + struct tomoyo_domain_info * const 1047 + domain, 1048 + const bool is_delete) 1049 + { 1050 + struct tomoyo_path_number_acl e = { 1051 + .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL, 1052 + .perm = 1 << type 1053 + }; 1054 + int error = is_delete ? -ENOENT : -ENOMEM; 1055 + if (!tomoyo_parse_name_union(filename, &e.name)) 1056 + return -EINVAL; 1057 + if (!tomoyo_parse_number_union(number, &e.number)) 1058 + goto out; 1059 + error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, 1060 + tomoyo_same_path_number_acl, 1061 + tomoyo_merge_path_number_acl); 1062 + out: 1063 + tomoyo_put_name_union(&e.name); 1064 + tomoyo_put_number_union(&e.number); 1065 + return error; 1066 + } 1067 + 1068 + /** 1069 + * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp". 1070 + * 1071 + * @type: Type of operation. 1072 + * @path: Pointer to "struct path". 1073 + * @number: Number. 1074 + * 1075 + * Returns 0 on success, negative value otherwise. 1076 + */ 1077 + int tomoyo_path_number_perm(const u8 type, struct path *path, 1078 + unsigned long number) 1079 + { 1080 + struct tomoyo_request_info r; 1081 + int error = -ENOMEM; 1082 + struct tomoyo_path_info buf; 1083 + int idx; 1084 + 1085 + if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type]) 1086 + == TOMOYO_CONFIG_DISABLED || !path->mnt || !path->dentry) 889 1087 return 0; 890 - return tomoyo_check_file_perm2(domain, filename, 1, "do_execve", mode); 1088 + idx = tomoyo_read_lock(); 1089 + if (!tomoyo_get_realpath(&buf, path)) 1090 + goto out; 1091 + if (type == TOMOYO_TYPE_MKDIR) 1092 + tomoyo_add_slash(&buf); 1093 + r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL; 1094 + r.param.path_number.operation = type; 1095 + r.param.path_number.filename = &buf; 1096 + r.param.path_number.number = number; 1097 + do { 1098 + tomoyo_check_acl(&r, tomoyo_check_path_number_acl); 1099 + error = tomoyo_audit_path_number_log(&r); 1100 + } while (error == TOMOYO_RETRY_REQUEST); 1101 + kfree(buf.name); 1102 + out: 1103 + tomoyo_read_unlock(idx); 1104 + if (r.mode != TOMOYO_CONFIG_ENFORCING) 1105 + error = 0; 1106 + return error; 891 1107 } 892 1108 893 1109 /** ··· 928 1096 { 929 1097 const u8 acc_mode = ACC_MODE(flag); 930 1098 int error = -ENOMEM; 931 - struct tomoyo_path_info *buf; 932 - const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); 933 - const bool is_enforce = (mode == 3); 1099 + struct tomoyo_path_info buf; 1100 + struct tomoyo_request_info r; 934 1101 int idx; 935 1102 936 - if (!mode || !path->mnt) 1103 + if (!path->mnt || 1104 + (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode))) 937 1105 return 0; 938 - if (acc_mode == 0) 939 - return 0; 940 - if (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode)) 941 - /* 942 - * I don't check directories here because mkdir() and rmdir() 943 - * don't call me. 944 - */ 945 - return 0; 1106 + buf.name = NULL; 1107 + r.mode = TOMOYO_CONFIG_DISABLED; 946 1108 idx = tomoyo_read_lock(); 947 - buf = tomoyo_get_path(path); 948 - if (!buf) 1109 + if (!tomoyo_get_realpath(&buf, path)) 949 1110 goto out; 950 1111 error = 0; 951 1112 /* ··· 946 1121 * we need to check "allow_rewrite" permission when the filename is not 947 1122 * opened for append mode or the filename is truncated at open time. 948 1123 */ 949 - if ((acc_mode & MAY_WRITE) && 950 - ((flag & O_TRUNC) || !(flag & O_APPEND)) && 951 - (tomoyo_is_no_rewrite_file(buf))) { 952 - error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE, 953 - buf, mode); 1124 + if ((acc_mode & MAY_WRITE) && !(flag & O_APPEND) 1125 + && tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_REWRITE) 1126 + != TOMOYO_CONFIG_DISABLED) { 1127 + if (!tomoyo_get_realpath(&buf, path)) { 1128 + error = -ENOMEM; 1129 + goto out; 1130 + } 1131 + if (tomoyo_no_rewrite_file(&buf)) 1132 + error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE, 1133 + &buf); 954 1134 } 955 - if (!error) 956 - error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open", 957 - mode); 958 - if (!error && (flag & O_TRUNC)) 959 - error = tomoyo_path_permission2(domain, TOMOYO_TYPE_TRUNCATE, 960 - buf, mode); 1135 + if (!error && acc_mode && 1136 + tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN) 1137 + != TOMOYO_CONFIG_DISABLED) { 1138 + u8 operation; 1139 + if (!buf.name && !tomoyo_get_realpath(&buf, path)) { 1140 + error = -ENOMEM; 1141 + goto out; 1142 + } 1143 + if (acc_mode == (MAY_READ | MAY_WRITE)) 1144 + operation = TOMOYO_TYPE_READ_WRITE; 1145 + else if (acc_mode == MAY_READ) 1146 + operation = TOMOYO_TYPE_READ; 1147 + else 1148 + operation = TOMOYO_TYPE_WRITE; 1149 + error = tomoyo_path_permission(&r, operation, &buf); 1150 + } 961 1151 out: 962 - kfree(buf); 1152 + kfree(buf.name); 963 1153 tomoyo_read_unlock(idx); 964 - if (!is_enforce) 1154 + if (r.mode != TOMOYO_CONFIG_ENFORCING) 965 1155 error = 0; 966 1156 return error; 967 1157 } 968 1158 969 1159 /** 970 - * tomoyo_path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate", "symlink", "ioctl", "chmod", "chown", "chgrp", "chroot", "mount" and "unmount". 1160 + * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "rewrite", "chroot" and "unmount". 971 1161 * 972 1162 * @operation: Type of operation. 973 1163 * @path: Pointer to "struct path". ··· 992 1152 int tomoyo_path_perm(const u8 operation, struct path *path) 993 1153 { 994 1154 int error = -ENOMEM; 995 - struct tomoyo_path_info *buf; 996 - struct tomoyo_domain_info *domain = tomoyo_domain(); 997 - const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); 998 - const bool is_enforce = (mode == 3); 1155 + struct tomoyo_path_info buf; 1156 + struct tomoyo_request_info r; 999 1157 int idx; 1000 1158 1001 - if (!mode || !path->mnt) 1159 + if (!path->mnt) 1002 1160 return 0; 1161 + if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation]) 1162 + == TOMOYO_CONFIG_DISABLED) 1163 + return 0; 1164 + buf.name = NULL; 1003 1165 idx = tomoyo_read_lock(); 1004 - buf = tomoyo_get_path(path); 1005 - if (!buf) 1166 + if (!tomoyo_get_realpath(&buf, path)) 1006 1167 goto out; 1007 1168 switch (operation) { 1008 - case TOMOYO_TYPE_MKDIR: 1169 + case TOMOYO_TYPE_REWRITE: 1170 + if (!tomoyo_no_rewrite_file(&buf)) { 1171 + error = 0; 1172 + goto out; 1173 + } 1174 + break; 1009 1175 case TOMOYO_TYPE_RMDIR: 1010 1176 case TOMOYO_TYPE_CHROOT: 1011 - if (!buf->is_dir) { 1012 - /* 1013 - * tomoyo_get_path() reserves space for appending "/." 1014 - */ 1015 - strcat((char *) buf->name, "/"); 1016 - tomoyo_fill_path_info(buf); 1017 - } 1177 + case TOMOYO_TYPE_UMOUNT: 1178 + tomoyo_add_slash(&buf); 1179 + break; 1018 1180 } 1019 - error = tomoyo_path_permission2(domain, operation, buf, mode); 1181 + error = tomoyo_path_permission(&r, operation, &buf); 1020 1182 out: 1021 - kfree(buf); 1183 + kfree(buf.name); 1022 1184 tomoyo_read_unlock(idx); 1023 - if (!is_enforce) 1185 + if (r.mode != TOMOYO_CONFIG_ENFORCING) 1024 1186 error = 0; 1025 1187 return error; 1026 1188 } 1027 1189 1028 1190 /** 1029 - * tomoyo_check_rewrite_permission - Check permission for "rewrite". 1191 + * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar". 1030 1192 * 1031 - * @filp: Pointer to "struct file". 1193 + * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK) 1194 + * @path: Pointer to "struct path". 1195 + * @mode: Create mode. 1196 + * @dev: Device number. 1032 1197 * 1033 1198 * Returns 0 on success, negative value otherwise. 1034 1199 */ 1035 - int tomoyo_check_rewrite_permission(struct file *filp) 1200 + int tomoyo_mkdev_perm(const u8 operation, struct path *path, 1201 + const unsigned int mode, unsigned int dev) 1036 1202 { 1203 + struct tomoyo_request_info r; 1037 1204 int error = -ENOMEM; 1038 - struct tomoyo_domain_info *domain = tomoyo_domain(); 1039 - const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); 1040 - const bool is_enforce = (mode == 3); 1041 - struct tomoyo_path_info *buf; 1205 + struct tomoyo_path_info buf; 1042 1206 int idx; 1043 1207 1044 - if (!mode || !filp->f_path.mnt) 1208 + if (!path->mnt || 1209 + tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation]) 1210 + == TOMOYO_CONFIG_DISABLED) 1045 1211 return 0; 1046 - 1047 1212 idx = tomoyo_read_lock(); 1048 - buf = tomoyo_get_path(&filp->f_path); 1049 - if (!buf) 1050 - goto out; 1051 - if (!tomoyo_is_no_rewrite_file(buf)) { 1052 - error = 0; 1053 - goto out; 1213 + error = -ENOMEM; 1214 + if (tomoyo_get_realpath(&buf, path)) { 1215 + dev = new_decode_dev(dev); 1216 + r.param_type = TOMOYO_TYPE_MKDEV_ACL; 1217 + r.param.mkdev.filename = &buf; 1218 + r.param.mkdev.operation = operation; 1219 + r.param.mkdev.mode = mode; 1220 + r.param.mkdev.major = MAJOR(dev); 1221 + r.param.mkdev.minor = MINOR(dev); 1222 + tomoyo_check_acl(&r, tomoyo_check_mkdev_acl); 1223 + error = tomoyo_audit_mkdev_log(&r); 1224 + kfree(buf.name); 1054 1225 } 1055 - error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE, buf, mode); 1056 - out: 1057 - kfree(buf); 1058 1226 tomoyo_read_unlock(idx); 1059 - if (!is_enforce) 1227 + if (r.mode != TOMOYO_CONFIG_ENFORCING) 1060 1228 error = 0; 1061 1229 return error; 1062 1230 } ··· 1082 1234 struct path *path2) 1083 1235 { 1084 1236 int error = -ENOMEM; 1085 - struct tomoyo_path_info *buf1, *buf2; 1086 - struct tomoyo_domain_info *domain = tomoyo_domain(); 1087 - const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); 1088 - const bool is_enforce = (mode == 3); 1089 - const char *msg; 1237 + struct tomoyo_path_info buf1; 1238 + struct tomoyo_path_info buf2; 1239 + struct tomoyo_request_info r; 1090 1240 int idx; 1091 1241 1092 - if (!mode || !path1->mnt || !path2->mnt) 1242 + if (!path1->mnt || !path2->mnt || 1243 + tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation]) 1244 + == TOMOYO_CONFIG_DISABLED) 1093 1245 return 0; 1246 + buf1.name = NULL; 1247 + buf2.name = NULL; 1094 1248 idx = tomoyo_read_lock(); 1095 - buf1 = tomoyo_get_path(path1); 1096 - buf2 = tomoyo_get_path(path2); 1097 - if (!buf1 || !buf2) 1249 + if (!tomoyo_get_realpath(&buf1, path1) || 1250 + !tomoyo_get_realpath(&buf2, path2)) 1098 1251 goto out; 1099 - { 1100 - struct dentry *dentry = path1->dentry; 1101 - if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) { 1102 - /* 1103 - * tomoyo_get_path() reserves space for appending "/." 1104 - */ 1105 - if (!buf1->is_dir) { 1106 - strcat((char *) buf1->name, "/"); 1107 - tomoyo_fill_path_info(buf1); 1108 - } 1109 - if (!buf2->is_dir) { 1110 - strcat((char *) buf2->name, "/"); 1111 - tomoyo_fill_path_info(buf2); 1112 - } 1113 - } 1114 - } 1115 - error = tomoyo_path2_acl(domain, operation, buf1, buf2); 1116 - msg = tomoyo_path22keyword(operation); 1117 - if (!error) 1118 - goto out; 1119 - if (tomoyo_verbose_mode(domain)) 1120 - printk(KERN_WARNING "TOMOYO-%s: Access '%s %s %s' " 1121 - "denied for %s\n", tomoyo_get_msg(is_enforce), 1122 - msg, buf1->name, buf2->name, 1123 - tomoyo_get_last_name(domain)); 1124 - if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { 1125 - const char *name1 = tomoyo_get_file_pattern(buf1)->name; 1126 - const char *name2 = tomoyo_get_file_pattern(buf2)->name; 1127 - tomoyo_update_path2_acl(operation, name1, name2, domain, 1128 - false); 1129 - } 1252 + switch (operation) { 1253 + struct dentry *dentry; 1254 + case TOMOYO_TYPE_RENAME: 1255 + case TOMOYO_TYPE_LINK: 1256 + dentry = path1->dentry; 1257 + if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode)) 1258 + break; 1259 + /* fall through */ 1260 + case TOMOYO_TYPE_PIVOT_ROOT: 1261 + tomoyo_add_slash(&buf1); 1262 + tomoyo_add_slash(&buf2); 1263 + break; 1264 + } 1265 + r.param_type = TOMOYO_TYPE_PATH2_ACL; 1266 + r.param.path2.operation = operation; 1267 + r.param.path2.filename1 = &buf1; 1268 + r.param.path2.filename2 = &buf2; 1269 + do { 1270 + tomoyo_check_acl(&r, tomoyo_check_path2_acl); 1271 + error = tomoyo_audit_path2_log(&r); 1272 + } while (error == TOMOYO_RETRY_REQUEST); 1130 1273 out: 1131 - kfree(buf1); 1132 - kfree(buf2); 1274 + kfree(buf1.name); 1275 + kfree(buf2.name); 1133 1276 tomoyo_read_unlock(idx); 1134 - if (!is_enforce) 1277 + if (r.mode != TOMOYO_CONFIG_ENFORCING) 1135 1278 error = 0; 1136 1279 return error; 1280 + } 1281 + 1282 + /** 1283 + * tomoyo_write_file - Update file related list. 1284 + * 1285 + * @data: String to parse. 1286 + * @domain: Pointer to "struct tomoyo_domain_info". 1287 + * @is_delete: True if it is a delete request. 1288 + * 1289 + * Returns 0 on success, negative value otherwise. 1290 + * 1291 + * Caller holds tomoyo_read_lock(). 1292 + */ 1293 + int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain, 1294 + const bool is_delete) 1295 + { 1296 + char *w[5]; 1297 + u8 type; 1298 + if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0]) 1299 + return -EINVAL; 1300 + if (strncmp(w[0], "allow_", 6)) 1301 + goto out; 1302 + w[0] += 6; 1303 + for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) { 1304 + if (strcmp(w[0], tomoyo_path_keyword[type])) 1305 + continue; 1306 + return tomoyo_update_path_acl(type, w[1], domain, is_delete); 1307 + } 1308 + if (!w[2][0]) 1309 + goto out; 1310 + for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) { 1311 + if (strcmp(w[0], tomoyo_path2_keyword[type])) 1312 + continue; 1313 + return tomoyo_update_path2_acl(type, w[1], w[2], domain, 1314 + is_delete); 1315 + } 1316 + for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) { 1317 + if (strcmp(w[0], tomoyo_path_number_keyword[type])) 1318 + continue; 1319 + return tomoyo_update_path_number_acl(type, w[1], w[2], domain, 1320 + is_delete); 1321 + } 1322 + if (!w[3][0] || !w[4][0]) 1323 + goto out; 1324 + for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) { 1325 + if (strcmp(w[0], tomoyo_mkdev_keyword[type])) 1326 + continue; 1327 + return tomoyo_update_mkdev_acl(type, w[1], w[2], w[3], 1328 + w[4], domain, is_delete); 1329 + } 1330 + out: 1331 + return -EINVAL; 1137 1332 }
+151 -209
security/tomoyo/gc.c
··· 11 11 #include <linux/kthread.h> 12 12 #include <linux/slab.h> 13 13 14 - enum tomoyo_gc_id { 15 - TOMOYO_ID_PATH_GROUP, 16 - TOMOYO_ID_PATH_GROUP_MEMBER, 17 - TOMOYO_ID_DOMAIN_INITIALIZER, 18 - TOMOYO_ID_DOMAIN_KEEPER, 19 - TOMOYO_ID_ALIAS, 20 - TOMOYO_ID_GLOBALLY_READABLE, 21 - TOMOYO_ID_PATTERN, 22 - TOMOYO_ID_NO_REWRITE, 23 - TOMOYO_ID_MANAGER, 24 - TOMOYO_ID_NAME, 25 - TOMOYO_ID_ACL, 26 - TOMOYO_ID_DOMAIN 27 - }; 28 - 29 - struct tomoyo_gc_entry { 14 + struct tomoyo_gc { 30 15 struct list_head list; 31 16 int type; 32 - void *element; 17 + struct list_head *element; 33 18 }; 34 19 static LIST_HEAD(tomoyo_gc_queue); 35 20 static DEFINE_MUTEX(tomoyo_gc_mutex); 36 21 37 22 /* Caller holds tomoyo_policy_lock mutex. */ 38 - static bool tomoyo_add_to_gc(const int type, void *element) 23 + static bool tomoyo_add_to_gc(const int type, struct list_head *element) 39 24 { 40 - struct tomoyo_gc_entry *entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 25 + struct tomoyo_gc *entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 41 26 if (!entry) 42 27 return false; 43 28 entry->type = type; 44 29 entry->element = element; 45 30 list_add(&entry->list, &tomoyo_gc_queue); 31 + list_del_rcu(element); 46 32 return true; 47 33 } 48 34 49 - static void tomoyo_del_allow_read 50 - (struct tomoyo_globally_readable_file_entry *ptr) 35 + static void tomoyo_del_allow_read(struct list_head *element) 51 36 { 37 + struct tomoyo_readable_file *ptr = 38 + container_of(element, typeof(*ptr), head.list); 52 39 tomoyo_put_name(ptr->filename); 53 40 } 54 41 55 - static void tomoyo_del_file_pattern(struct tomoyo_pattern_entry *ptr) 42 + static void tomoyo_del_file_pattern(struct list_head *element) 56 43 { 44 + struct tomoyo_no_pattern *ptr = 45 + container_of(element, typeof(*ptr), head.list); 57 46 tomoyo_put_name(ptr->pattern); 58 47 } 59 48 60 - static void tomoyo_del_no_rewrite(struct tomoyo_no_rewrite_entry *ptr) 49 + static void tomoyo_del_no_rewrite(struct list_head *element) 61 50 { 51 + struct tomoyo_no_rewrite *ptr = 52 + container_of(element, typeof(*ptr), head.list); 62 53 tomoyo_put_name(ptr->pattern); 63 54 } 64 55 65 - static void tomoyo_del_domain_initializer 66 - (struct tomoyo_domain_initializer_entry *ptr) 56 + static void tomoyo_del_transition_control(struct list_head *element) 67 57 { 58 + struct tomoyo_transition_control *ptr = 59 + container_of(element, typeof(*ptr), head.list); 68 60 tomoyo_put_name(ptr->domainname); 69 61 tomoyo_put_name(ptr->program); 70 62 } 71 63 72 - static void tomoyo_del_domain_keeper(struct tomoyo_domain_keeper_entry *ptr) 64 + static void tomoyo_del_aggregator(struct list_head *element) 73 65 { 74 - tomoyo_put_name(ptr->domainname); 75 - tomoyo_put_name(ptr->program); 76 - } 77 - 78 - static void tomoyo_del_alias(struct tomoyo_alias_entry *ptr) 79 - { 66 + struct tomoyo_aggregator *ptr = 67 + container_of(element, typeof(*ptr), head.list); 80 68 tomoyo_put_name(ptr->original_name); 81 - tomoyo_put_name(ptr->aliased_name); 69 + tomoyo_put_name(ptr->aggregated_name); 82 70 } 83 71 84 - static void tomoyo_del_manager(struct tomoyo_policy_manager_entry *ptr) 72 + static void tomoyo_del_manager(struct list_head *element) 85 73 { 74 + struct tomoyo_manager *ptr = 75 + container_of(element, typeof(*ptr), head.list); 86 76 tomoyo_put_name(ptr->manager); 87 77 } 88 78 89 - static void tomoyo_del_acl(struct tomoyo_acl_info *acl) 79 + static void tomoyo_del_acl(struct list_head *element) 90 80 { 81 + struct tomoyo_acl_info *acl = 82 + container_of(element, typeof(*acl), list); 91 83 switch (acl->type) { 92 84 case TOMOYO_TYPE_PATH_ACL: 93 85 { ··· 96 104 tomoyo_put_name_union(&entry->name2); 97 105 } 98 106 break; 99 - default: 100 - printk(KERN_WARNING "Unknown type\n"); 107 + case TOMOYO_TYPE_PATH_NUMBER_ACL: 108 + { 109 + struct tomoyo_path_number_acl *entry 110 + = container_of(acl, typeof(*entry), head); 111 + tomoyo_put_name_union(&entry->name); 112 + tomoyo_put_number_union(&entry->number); 113 + } 114 + break; 115 + case TOMOYO_TYPE_MKDEV_ACL: 116 + { 117 + struct tomoyo_mkdev_acl *entry 118 + = container_of(acl, typeof(*entry), head); 119 + tomoyo_put_name_union(&entry->name); 120 + tomoyo_put_number_union(&entry->mode); 121 + tomoyo_put_number_union(&entry->major); 122 + tomoyo_put_number_union(&entry->minor); 123 + } 124 + break; 125 + case TOMOYO_TYPE_MOUNT_ACL: 126 + { 127 + struct tomoyo_mount_acl *entry 128 + = container_of(acl, typeof(*entry), head); 129 + tomoyo_put_name_union(&entry->dev_name); 130 + tomoyo_put_name_union(&entry->dir_name); 131 + tomoyo_put_name_union(&entry->fs_type); 132 + tomoyo_put_number_union(&entry->flags); 133 + } 101 134 break; 102 135 } 103 136 } 104 137 105 - static bool tomoyo_del_domain(struct tomoyo_domain_info *domain) 138 + static bool tomoyo_del_domain(struct list_head *element) 106 139 { 140 + struct tomoyo_domain_info *domain = 141 + container_of(element, typeof(*domain), list); 107 142 struct tomoyo_acl_info *acl; 108 143 struct tomoyo_acl_info *tmp; 109 144 /* ··· 158 139 if (atomic_read(&domain->users)) 159 140 return false; 160 141 list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) { 161 - tomoyo_del_acl(acl); 142 + tomoyo_del_acl(&acl->list); 162 143 tomoyo_memory_free(acl); 163 144 } 164 145 tomoyo_put_name(domain->domainname); ··· 166 147 } 167 148 168 149 169 - static void tomoyo_del_name(const struct tomoyo_name_entry *ptr) 150 + static void tomoyo_del_name(struct list_head *element) 170 151 { 152 + const struct tomoyo_name *ptr = 153 + container_of(element, typeof(*ptr), list); 171 154 } 172 155 173 - static void tomoyo_del_path_group_member(struct tomoyo_path_group_member 174 - *member) 156 + static void tomoyo_del_path_group(struct list_head *element) 175 157 { 158 + struct tomoyo_path_group *member = 159 + container_of(element, typeof(*member), head.list); 176 160 tomoyo_put_name(member->member_name); 177 161 } 178 162 179 - static void tomoyo_del_path_group(struct tomoyo_path_group *group) 163 + static void tomoyo_del_group(struct list_head *element) 180 164 { 165 + struct tomoyo_group *group = 166 + container_of(element, typeof(*group), list); 181 167 tomoyo_put_name(group->group_name); 168 + } 169 + 170 + static void tomoyo_del_number_group(struct list_head *element) 171 + { 172 + struct tomoyo_number_group *member = 173 + container_of(element, typeof(*member), head.list); 174 + } 175 + 176 + static bool tomoyo_collect_member(struct list_head *member_list, int id) 177 + { 178 + struct tomoyo_acl_head *member; 179 + list_for_each_entry(member, member_list, list) { 180 + if (!member->is_deleted) 181 + continue; 182 + if (!tomoyo_add_to_gc(id, &member->list)) 183 + return false; 184 + } 185 + return true; 186 + } 187 + 188 + static bool tomoyo_collect_acl(struct tomoyo_domain_info *domain) 189 + { 190 + struct tomoyo_acl_info *acl; 191 + list_for_each_entry(acl, &domain->acl_info_list, list) { 192 + if (!acl->is_deleted) 193 + continue; 194 + if (!tomoyo_add_to_gc(TOMOYO_ID_ACL, &acl->list)) 195 + return false; 196 + } 197 + return true; 182 198 } 183 199 184 200 static void tomoyo_collect_entry(void) 185 201 { 202 + int i; 186 203 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 187 204 return; 188 - { 189 - struct tomoyo_globally_readable_file_entry *ptr; 190 - list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, 191 - list) { 192 - if (!ptr->is_deleted) 193 - continue; 194 - if (tomoyo_add_to_gc(TOMOYO_ID_GLOBALLY_READABLE, ptr)) 195 - list_del_rcu(&ptr->list); 196 - else 197 - break; 198 - } 199 - } 200 - { 201 - struct tomoyo_pattern_entry *ptr; 202 - list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { 203 - if (!ptr->is_deleted) 204 - continue; 205 - if (tomoyo_add_to_gc(TOMOYO_ID_PATTERN, ptr)) 206 - list_del_rcu(&ptr->list); 207 - else 208 - break; 209 - } 210 - } 211 - { 212 - struct tomoyo_no_rewrite_entry *ptr; 213 - list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { 214 - if (!ptr->is_deleted) 215 - continue; 216 - if (tomoyo_add_to_gc(TOMOYO_ID_NO_REWRITE, ptr)) 217 - list_del_rcu(&ptr->list); 218 - else 219 - break; 220 - } 221 - } 222 - { 223 - struct tomoyo_domain_initializer_entry *ptr; 224 - list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, 225 - list) { 226 - if (!ptr->is_deleted) 227 - continue; 228 - if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_INITIALIZER, ptr)) 229 - list_del_rcu(&ptr->list); 230 - else 231 - break; 232 - } 233 - } 234 - { 235 - struct tomoyo_domain_keeper_entry *ptr; 236 - list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { 237 - if (!ptr->is_deleted) 238 - continue; 239 - if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_KEEPER, ptr)) 240 - list_del_rcu(&ptr->list); 241 - else 242 - break; 243 - } 244 - } 245 - { 246 - struct tomoyo_alias_entry *ptr; 247 - list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { 248 - if (!ptr->is_deleted) 249 - continue; 250 - if (tomoyo_add_to_gc(TOMOYO_ID_ALIAS, ptr)) 251 - list_del_rcu(&ptr->list); 252 - else 253 - break; 254 - } 255 - } 256 - { 257 - struct tomoyo_policy_manager_entry *ptr; 258 - list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, 259 - list) { 260 - if (!ptr->is_deleted) 261 - continue; 262 - if (tomoyo_add_to_gc(TOMOYO_ID_MANAGER, ptr)) 263 - list_del_rcu(&ptr->list); 264 - else 265 - break; 266 - } 205 + for (i = 0; i < TOMOYO_MAX_POLICY; i++) { 206 + if (!tomoyo_collect_member(&tomoyo_policy_list[i], i)) 207 + goto unlock; 267 208 } 268 209 { 269 210 struct tomoyo_domain_info *domain; 270 211 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { 271 - struct tomoyo_acl_info *acl; 272 - list_for_each_entry_rcu(acl, &domain->acl_info_list, 273 - list) { 274 - switch (acl->type) { 275 - case TOMOYO_TYPE_PATH_ACL: 276 - if (container_of(acl, 277 - struct tomoyo_path_acl, 278 - head)->perm || 279 - container_of(acl, 280 - struct tomoyo_path_acl, 281 - head)->perm_high) 282 - continue; 283 - break; 284 - case TOMOYO_TYPE_PATH2_ACL: 285 - if (container_of(acl, 286 - struct tomoyo_path2_acl, 287 - head)->perm) 288 - continue; 289 - break; 290 - default: 291 - continue; 292 - } 293 - if (tomoyo_add_to_gc(TOMOYO_ID_ACL, acl)) 294 - list_del_rcu(&acl->list); 295 - else 296 - break; 297 - } 212 + if (!tomoyo_collect_acl(domain)) 213 + goto unlock; 298 214 if (!domain->is_deleted || atomic_read(&domain->users)) 299 215 continue; 300 216 /* ··· 237 283 * refer this domain after successful execve(). 238 284 * We recheck domain->users after SRCU synchronization. 239 285 */ 240 - if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, domain)) 241 - list_del_rcu(&domain->list); 242 - else 243 - break; 286 + if (!tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, &domain->list)) 287 + goto unlock; 244 288 } 245 289 } 246 - { 247 - int i; 248 - for (i = 0; i < TOMOYO_MAX_HASH; i++) { 249 - struct tomoyo_name_entry *ptr; 250 - list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], 251 - list) { 252 - if (atomic_read(&ptr->users)) 253 - continue; 254 - if (tomoyo_add_to_gc(TOMOYO_ID_NAME, ptr)) 255 - list_del_rcu(&ptr->list); 256 - else { 257 - i = TOMOYO_MAX_HASH; 258 - break; 259 - } 260 - } 290 + for (i = 0; i < TOMOYO_MAX_HASH; i++) { 291 + struct tomoyo_name *ptr; 292 + list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], list) { 293 + if (atomic_read(&ptr->users)) 294 + continue; 295 + if (!tomoyo_add_to_gc(TOMOYO_ID_NAME, &ptr->list)) 296 + goto unlock; 261 297 } 262 298 } 263 - { 264 - struct tomoyo_path_group *group; 265 - list_for_each_entry_rcu(group, &tomoyo_path_group_list, list) { 266 - struct tomoyo_path_group_member *member; 267 - list_for_each_entry_rcu(member, &group->member_list, 268 - list) { 269 - if (!member->is_deleted) 270 - continue; 271 - if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP_MEMBER, 272 - member)) 273 - list_del_rcu(&member->list); 274 - else 275 - break; 276 - } 299 + for (i = 0; i < TOMOYO_MAX_GROUP; i++) { 300 + struct list_head *list = &tomoyo_group_list[i]; 301 + int id; 302 + struct tomoyo_group *group; 303 + switch (i) { 304 + case 0: 305 + id = TOMOYO_ID_PATH_GROUP; 306 + break; 307 + default: 308 + id = TOMOYO_ID_NUMBER_GROUP; 309 + break; 310 + } 311 + list_for_each_entry(group, list, list) { 312 + if (!tomoyo_collect_member(&group->member_list, id)) 313 + goto unlock; 277 314 if (!list_empty(&group->member_list) || 278 315 atomic_read(&group->users)) 279 316 continue; 280 - if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP, group)) 281 - list_del_rcu(&group->list); 282 - else 283 - break; 317 + if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, &group->list)) 318 + goto unlock; 284 319 } 285 320 } 321 + unlock: 286 322 mutex_unlock(&tomoyo_policy_lock); 287 323 } 288 324 289 325 static void tomoyo_kfree_entry(void) 290 326 { 291 - struct tomoyo_gc_entry *p; 292 - struct tomoyo_gc_entry *tmp; 327 + struct tomoyo_gc *p; 328 + struct tomoyo_gc *tmp; 293 329 294 330 list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) { 331 + struct list_head *element = p->element; 295 332 switch (p->type) { 296 - case TOMOYO_ID_DOMAIN_INITIALIZER: 297 - tomoyo_del_domain_initializer(p->element); 333 + case TOMOYO_ID_TRANSITION_CONTROL: 334 + tomoyo_del_transition_control(element); 298 335 break; 299 - case TOMOYO_ID_DOMAIN_KEEPER: 300 - tomoyo_del_domain_keeper(p->element); 301 - break; 302 - case TOMOYO_ID_ALIAS: 303 - tomoyo_del_alias(p->element); 336 + case TOMOYO_ID_AGGREGATOR: 337 + tomoyo_del_aggregator(element); 304 338 break; 305 339 case TOMOYO_ID_GLOBALLY_READABLE: 306 - tomoyo_del_allow_read(p->element); 340 + tomoyo_del_allow_read(element); 307 341 break; 308 342 case TOMOYO_ID_PATTERN: 309 - tomoyo_del_file_pattern(p->element); 343 + tomoyo_del_file_pattern(element); 310 344 break; 311 345 case TOMOYO_ID_NO_REWRITE: 312 - tomoyo_del_no_rewrite(p->element); 346 + tomoyo_del_no_rewrite(element); 313 347 break; 314 348 case TOMOYO_ID_MANAGER: 315 - tomoyo_del_manager(p->element); 349 + tomoyo_del_manager(element); 316 350 break; 317 351 case TOMOYO_ID_NAME: 318 - tomoyo_del_name(p->element); 352 + tomoyo_del_name(element); 319 353 break; 320 354 case TOMOYO_ID_ACL: 321 - tomoyo_del_acl(p->element); 355 + tomoyo_del_acl(element); 322 356 break; 323 357 case TOMOYO_ID_DOMAIN: 324 - if (!tomoyo_del_domain(p->element)) 358 + if (!tomoyo_del_domain(element)) 325 359 continue; 326 360 break; 327 - case TOMOYO_ID_PATH_GROUP_MEMBER: 328 - tomoyo_del_path_group_member(p->element); 329 - break; 330 361 case TOMOYO_ID_PATH_GROUP: 331 - tomoyo_del_path_group(p->element); 362 + tomoyo_del_path_group(element); 332 363 break; 333 - default: 334 - printk(KERN_WARNING "Unknown type\n"); 364 + case TOMOYO_ID_GROUP: 365 + tomoyo_del_group(element); 366 + break; 367 + case TOMOYO_ID_NUMBER_GROUP: 368 + tomoyo_del_number_group(element); 335 369 break; 336 370 } 337 - tomoyo_memory_free(p->element); 371 + tomoyo_memory_free(element); 338 372 list_del(&p->list); 339 373 kfree(p); 340 374 }
+130
security/tomoyo/group.c
··· 1 + /* 2 + * security/tomoyo/group.c 3 + * 4 + * Copyright (C) 2005-2010 NTT DATA CORPORATION 5 + */ 6 + 7 + #include <linux/slab.h> 8 + #include "common.h" 9 + 10 + static bool tomoyo_same_path_group(const struct tomoyo_acl_head *a, 11 + const struct tomoyo_acl_head *b) 12 + { 13 + return container_of(a, struct tomoyo_path_group, head)->member_name == 14 + container_of(b, struct tomoyo_path_group, head)->member_name; 15 + } 16 + 17 + static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a, 18 + const struct tomoyo_acl_head *b) 19 + { 20 + return !memcmp(&container_of(a, struct tomoyo_number_group, head) 21 + ->number, 22 + &container_of(b, struct tomoyo_number_group, head) 23 + ->number, 24 + sizeof(container_of(a, struct tomoyo_number_group, head) 25 + ->number)); 26 + } 27 + 28 + /** 29 + * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group" list. 30 + * 31 + * @data: String to parse. 32 + * @is_delete: True if it is a delete request. 33 + * @type: Type of this group. 34 + * 35 + * Returns 0 on success, negative value otherwise. 36 + */ 37 + int tomoyo_write_group(char *data, const bool is_delete, const u8 type) 38 + { 39 + struct tomoyo_group *group; 40 + struct list_head *member; 41 + char *w[2]; 42 + int error = -EINVAL; 43 + if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0]) 44 + return -EINVAL; 45 + group = tomoyo_get_group(w[0], type); 46 + if (!group) 47 + return -ENOMEM; 48 + member = &group->member_list; 49 + if (type == TOMOYO_PATH_GROUP) { 50 + struct tomoyo_path_group e = { }; 51 + e.member_name = tomoyo_get_name(w[1]); 52 + if (!e.member_name) { 53 + error = -ENOMEM; 54 + goto out; 55 + } 56 + error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 57 + member, tomoyo_same_path_group); 58 + tomoyo_put_name(e.member_name); 59 + } else if (type == TOMOYO_NUMBER_GROUP) { 60 + struct tomoyo_number_group e = { }; 61 + if (w[1][0] == '@' 62 + || !tomoyo_parse_number_union(w[1], &e.number) 63 + || e.number.values[0] > e.number.values[1]) 64 + goto out; 65 + error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 66 + member, tomoyo_same_number_group); 67 + /* 68 + * tomoyo_put_number_union() is not needed because 69 + * w[1][0] != '@'. 70 + */ 71 + } 72 + out: 73 + tomoyo_put_group(group); 74 + return error; 75 + } 76 + 77 + /** 78 + * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group. 79 + * 80 + * @pathname: The name of pathname. 81 + * @group: Pointer to "struct tomoyo_path_group". 82 + * 83 + * Returns matched member's pathname if @pathname matches pathnames in @group, 84 + * NULL otherwise. 85 + * 86 + * Caller holds tomoyo_read_lock(). 87 + */ 88 + const struct tomoyo_path_info * 89 + tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, 90 + const struct tomoyo_group *group) 91 + { 92 + struct tomoyo_path_group *member; 93 + list_for_each_entry_rcu(member, &group->member_list, head.list) { 94 + if (member->head.is_deleted) 95 + continue; 96 + if (!tomoyo_path_matches_pattern(pathname, member->member_name)) 97 + continue; 98 + return member->member_name; 99 + } 100 + return NULL; 101 + } 102 + 103 + /** 104 + * tomoyo_number_matches_group - Check whether the given number matches members of the given number group. 105 + * 106 + * @min: Min number. 107 + * @max: Max number. 108 + * @group: Pointer to "struct tomoyo_number_group". 109 + * 110 + * Returns true if @min and @max partially overlaps @group, false otherwise. 111 + * 112 + * Caller holds tomoyo_read_lock(). 113 + */ 114 + bool tomoyo_number_matches_group(const unsigned long min, 115 + const unsigned long max, 116 + const struct tomoyo_group *group) 117 + { 118 + struct tomoyo_number_group *member; 119 + bool matched = false; 120 + list_for_each_entry_rcu(member, &group->member_list, head.list) { 121 + if (member->head.is_deleted) 122 + continue; 123 + if (min > member->number.values[1] || 124 + max < member->number.values[0]) 125 + continue; 126 + matched = true; 127 + break; 128 + } 129 + return matched; 130 + }
+81
security/tomoyo/load_policy.c
··· 1 + /* 2 + * security/tomoyo/load_policy.c 3 + * 4 + * Policy loader launcher for TOMOYO. 5 + * 6 + * Copyright (C) 2005-2010 NTT DATA CORPORATION 7 + */ 8 + 9 + #include "common.h" 10 + 11 + /* path to policy loader */ 12 + static const char *tomoyo_loader = "/sbin/tomoyo-init"; 13 + 14 + /** 15 + * tomoyo_policy_loader_exists - Check whether /sbin/tomoyo-init exists. 16 + * 17 + * Returns true if /sbin/tomoyo-init exists, false otherwise. 18 + */ 19 + static bool tomoyo_policy_loader_exists(void) 20 + { 21 + /* 22 + * Don't activate MAC if the policy loader doesn't exist. 23 + * If the initrd includes /sbin/init but real-root-dev has not 24 + * mounted on / yet, activating MAC will block the system since 25 + * policies are not loaded yet. 26 + * Thus, let do_execve() call this function everytime. 27 + */ 28 + struct path path; 29 + 30 + if (kern_path(tomoyo_loader, LOOKUP_FOLLOW, &path)) { 31 + printk(KERN_INFO "Not activating Mandatory Access Control now " 32 + "since %s doesn't exist.\n", tomoyo_loader); 33 + return false; 34 + } 35 + path_put(&path); 36 + return true; 37 + } 38 + 39 + /** 40 + * tomoyo_load_policy - Run external policy loader to load policy. 41 + * 42 + * @filename: The program about to start. 43 + * 44 + * This function checks whether @filename is /sbin/init , and if so 45 + * invoke /sbin/tomoyo-init and wait for the termination of /sbin/tomoyo-init 46 + * and then continues invocation of /sbin/init. 47 + * /sbin/tomoyo-init reads policy files in /etc/tomoyo/ directory and 48 + * writes to /sys/kernel/security/tomoyo/ interfaces. 49 + * 50 + * Returns nothing. 51 + */ 52 + void tomoyo_load_policy(const char *filename) 53 + { 54 + char *argv[2]; 55 + char *envp[3]; 56 + 57 + if (tomoyo_policy_loaded) 58 + return; 59 + /* 60 + * Check filename is /sbin/init or /sbin/tomoyo-start. 61 + * /sbin/tomoyo-start is a dummy filename in case where /sbin/init can't 62 + * be passed. 63 + * You can create /sbin/tomoyo-start by 64 + * "ln -s /bin/true /sbin/tomoyo-start". 65 + */ 66 + if (strcmp(filename, "/sbin/init") && 67 + strcmp(filename, "/sbin/tomoyo-start")) 68 + return; 69 + if (!tomoyo_policy_loader_exists()) 70 + return; 71 + 72 + printk(KERN_INFO "Calling %s to load policy. Please wait.\n", 73 + tomoyo_loader); 74 + argv[0] = (char *) tomoyo_loader; 75 + argv[1] = NULL; 76 + envp[0] = "HOME=/"; 77 + envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; 78 + envp[2] = NULL; 79 + call_usermodehelper(argv[0], argv, envp, 1); 80 + tomoyo_check_profile(); 81 + }
+282
security/tomoyo/memory.c
··· 1 + /* 2 + * security/tomoyo/memory.c 3 + * 4 + * Memory management functions for TOMOYO. 5 + * 6 + * Copyright (C) 2005-2010 NTT DATA CORPORATION 7 + */ 8 + 9 + #include <linux/hash.h> 10 + #include <linux/slab.h> 11 + #include "common.h" 12 + 13 + /** 14 + * tomoyo_warn_oom - Print out of memory warning message. 15 + * 16 + * @function: Function's name. 17 + */ 18 + void tomoyo_warn_oom(const char *function) 19 + { 20 + /* Reduce error messages. */ 21 + static pid_t tomoyo_last_pid; 22 + const pid_t pid = current->pid; 23 + if (tomoyo_last_pid != pid) { 24 + printk(KERN_WARNING "ERROR: Out of memory at %s.\n", 25 + function); 26 + tomoyo_last_pid = pid; 27 + } 28 + if (!tomoyo_policy_loaded) 29 + panic("MAC Initialization failed.\n"); 30 + } 31 + 32 + /* Memory allocated for policy. */ 33 + static atomic_t tomoyo_policy_memory_size; 34 + /* Quota for holding policy. */ 35 + static unsigned int tomoyo_quota_for_policy; 36 + 37 + /** 38 + * tomoyo_memory_ok - Check memory quota. 39 + * 40 + * @ptr: Pointer to allocated memory. 41 + * 42 + * Returns true on success, false otherwise. 43 + * 44 + * Returns true if @ptr is not NULL and quota not exceeded, false otherwise. 45 + */ 46 + bool tomoyo_memory_ok(void *ptr) 47 + { 48 + size_t s = ptr ? ksize(ptr) : 0; 49 + atomic_add(s, &tomoyo_policy_memory_size); 50 + if (ptr && (!tomoyo_quota_for_policy || 51 + atomic_read(&tomoyo_policy_memory_size) 52 + <= tomoyo_quota_for_policy)) { 53 + memset(ptr, 0, s); 54 + return true; 55 + } 56 + atomic_sub(s, &tomoyo_policy_memory_size); 57 + tomoyo_warn_oom(__func__); 58 + return false; 59 + } 60 + 61 + /** 62 + * tomoyo_commit_ok - Check memory quota. 63 + * 64 + * @data: Data to copy from. 65 + * @size: Size in byte. 66 + * 67 + * Returns pointer to allocated memory on success, NULL otherwise. 68 + * @data is zero-cleared on success. 69 + */ 70 + void *tomoyo_commit_ok(void *data, const unsigned int size) 71 + { 72 + void *ptr = kzalloc(size, GFP_NOFS); 73 + if (tomoyo_memory_ok(ptr)) { 74 + memmove(ptr, data, size); 75 + memset(data, 0, size); 76 + return ptr; 77 + } 78 + return NULL; 79 + } 80 + 81 + /** 82 + * tomoyo_memory_free - Free memory for elements. 83 + * 84 + * @ptr: Pointer to allocated memory. 85 + */ 86 + void tomoyo_memory_free(void *ptr) 87 + { 88 + atomic_sub(ksize(ptr), &tomoyo_policy_memory_size); 89 + kfree(ptr); 90 + } 91 + 92 + /** 93 + * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group". 94 + * 95 + * @group_name: The name of address group. 96 + * @idx: Index number. 97 + * 98 + * Returns pointer to "struct tomoyo_group" on success, NULL otherwise. 99 + */ 100 + struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx) 101 + { 102 + struct tomoyo_group e = { }; 103 + struct tomoyo_group *group = NULL; 104 + bool found = false; 105 + if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP) 106 + return NULL; 107 + e.group_name = tomoyo_get_name(group_name); 108 + if (!e.group_name) 109 + return NULL; 110 + if (mutex_lock_interruptible(&tomoyo_policy_lock)) 111 + goto out; 112 + list_for_each_entry(group, &tomoyo_group_list[idx], list) { 113 + if (e.group_name != group->group_name) 114 + continue; 115 + atomic_inc(&group->users); 116 + found = true; 117 + break; 118 + } 119 + if (!found) { 120 + struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e)); 121 + if (entry) { 122 + INIT_LIST_HEAD(&entry->member_list); 123 + atomic_set(&entry->users, 1); 124 + list_add_tail_rcu(&entry->list, 125 + &tomoyo_group_list[idx]); 126 + group = entry; 127 + found = true; 128 + } 129 + } 130 + mutex_unlock(&tomoyo_policy_lock); 131 + out: 132 + tomoyo_put_name(e.group_name); 133 + return found ? group : NULL; 134 + } 135 + 136 + /* 137 + * tomoyo_name_list is used for holding string data used by TOMOYO. 138 + * Since same string data is likely used for multiple times (e.g. 139 + * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of 140 + * "const struct tomoyo_path_info *". 141 + */ 142 + struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; 143 + 144 + /** 145 + * tomoyo_get_name - Allocate permanent memory for string data. 146 + * 147 + * @name: The string to store into the permernent memory. 148 + * 149 + * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. 150 + */ 151 + const struct tomoyo_path_info *tomoyo_get_name(const char *name) 152 + { 153 + struct tomoyo_name *ptr; 154 + unsigned int hash; 155 + int len; 156 + int allocated_len; 157 + struct list_head *head; 158 + 159 + if (!name) 160 + return NULL; 161 + len = strlen(name) + 1; 162 + hash = full_name_hash((const unsigned char *) name, len - 1); 163 + head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; 164 + if (mutex_lock_interruptible(&tomoyo_policy_lock)) 165 + return NULL; 166 + list_for_each_entry(ptr, head, list) { 167 + if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) 168 + continue; 169 + atomic_inc(&ptr->users); 170 + goto out; 171 + } 172 + ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS); 173 + allocated_len = ptr ? ksize(ptr) : 0; 174 + if (!ptr || (tomoyo_quota_for_policy && 175 + atomic_read(&tomoyo_policy_memory_size) + allocated_len 176 + > tomoyo_quota_for_policy)) { 177 + kfree(ptr); 178 + ptr = NULL; 179 + tomoyo_warn_oom(__func__); 180 + goto out; 181 + } 182 + atomic_add(allocated_len, &tomoyo_policy_memory_size); 183 + ptr->entry.name = ((char *) ptr) + sizeof(*ptr); 184 + memmove((char *) ptr->entry.name, name, len); 185 + atomic_set(&ptr->users, 1); 186 + tomoyo_fill_path_info(&ptr->entry); 187 + list_add_tail(&ptr->list, head); 188 + out: 189 + mutex_unlock(&tomoyo_policy_lock); 190 + return ptr ? &ptr->entry : NULL; 191 + } 192 + 193 + /** 194 + * tomoyo_mm_init - Initialize mm related code. 195 + */ 196 + void __init tomoyo_mm_init(void) 197 + { 198 + int idx; 199 + 200 + for (idx = 0; idx < TOMOYO_MAX_POLICY; idx++) 201 + INIT_LIST_HEAD(&tomoyo_policy_list[idx]); 202 + for (idx = 0; idx < TOMOYO_MAX_GROUP; idx++) 203 + INIT_LIST_HEAD(&tomoyo_group_list[idx]); 204 + for (idx = 0; idx < TOMOYO_MAX_HASH; idx++) 205 + INIT_LIST_HEAD(&tomoyo_name_list[idx]); 206 + INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); 207 + tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME); 208 + list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list); 209 + idx = tomoyo_read_lock(); 210 + if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain) 211 + panic("Can't register tomoyo_kernel_domain"); 212 + { 213 + /* Load built-in policy. */ 214 + tomoyo_write_transition_control("/sbin/hotplug", false, 215 + TOMOYO_TRANSITION_CONTROL_INITIALIZE); 216 + tomoyo_write_transition_control("/sbin/modprobe", false, 217 + TOMOYO_TRANSITION_CONTROL_INITIALIZE); 218 + } 219 + tomoyo_read_unlock(idx); 220 + } 221 + 222 + 223 + /* Memory allocated for query lists. */ 224 + unsigned int tomoyo_query_memory_size; 225 + /* Quota for holding query lists. */ 226 + unsigned int tomoyo_quota_for_query; 227 + 228 + /** 229 + * tomoyo_read_memory_counter - Check for memory usage in bytes. 230 + * 231 + * @head: Pointer to "struct tomoyo_io_buffer". 232 + * 233 + * Returns memory usage. 234 + */ 235 + void tomoyo_read_memory_counter(struct tomoyo_io_buffer *head) 236 + { 237 + if (!head->r.eof) { 238 + const unsigned int policy 239 + = atomic_read(&tomoyo_policy_memory_size); 240 + const unsigned int query = tomoyo_query_memory_size; 241 + char buffer[64]; 242 + 243 + memset(buffer, 0, sizeof(buffer)); 244 + if (tomoyo_quota_for_policy) 245 + snprintf(buffer, sizeof(buffer) - 1, 246 + " (Quota: %10u)", 247 + tomoyo_quota_for_policy); 248 + else 249 + buffer[0] = '\0'; 250 + tomoyo_io_printf(head, "Policy: %10u%s\n", policy, 251 + buffer); 252 + if (tomoyo_quota_for_query) 253 + snprintf(buffer, sizeof(buffer) - 1, 254 + " (Quota: %10u)", 255 + tomoyo_quota_for_query); 256 + else 257 + buffer[0] = '\0'; 258 + tomoyo_io_printf(head, "Query lists: %10u%s\n", query, 259 + buffer); 260 + tomoyo_io_printf(head, "Total: %10u\n", policy + query); 261 + head->r.eof = true; 262 + } 263 + } 264 + 265 + /** 266 + * tomoyo_write_memory_quota - Set memory quota. 267 + * 268 + * @head: Pointer to "struct tomoyo_io_buffer". 269 + * 270 + * Returns 0. 271 + */ 272 + int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head) 273 + { 274 + char *data = head->write_buf; 275 + unsigned int size; 276 + 277 + if (sscanf(data, "Policy: %u", &size) == 1) 278 + tomoyo_quota_for_policy = size; 279 + else if (sscanf(data, "Query lists: %u", &size) == 1) 280 + tomoyo_quota_for_query = size; 281 + return 0; 282 + }
+284
security/tomoyo/mount.c
··· 1 + /* 2 + * security/tomoyo/mount.c 3 + * 4 + * Copyright (C) 2005-2010 NTT DATA CORPORATION 5 + */ 6 + 7 + #include <linux/slab.h> 8 + #include "common.h" 9 + 10 + /* Keywords for mount restrictions. */ 11 + 12 + /* Allow to call 'mount --bind /source_dir /dest_dir' */ 13 + #define TOMOYO_MOUNT_BIND_KEYWORD "--bind" 14 + /* Allow to call 'mount --move /old_dir /new_dir ' */ 15 + #define TOMOYO_MOUNT_MOVE_KEYWORD "--move" 16 + /* Allow to call 'mount -o remount /dir ' */ 17 + #define TOMOYO_MOUNT_REMOUNT_KEYWORD "--remount" 18 + /* Allow to call 'mount --make-unbindable /dir' */ 19 + #define TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD "--make-unbindable" 20 + /* Allow to call 'mount --make-private /dir' */ 21 + #define TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD "--make-private" 22 + /* Allow to call 'mount --make-slave /dir' */ 23 + #define TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD "--make-slave" 24 + /* Allow to call 'mount --make-shared /dir' */ 25 + #define TOMOYO_MOUNT_MAKE_SHARED_KEYWORD "--make-shared" 26 + 27 + /** 28 + * tomoyo_audit_mount_log - Audit mount log. 29 + * 30 + * @r: Pointer to "struct tomoyo_request_info". 31 + * 32 + * Returns 0 on success, negative value otherwise. 33 + */ 34 + static int tomoyo_audit_mount_log(struct tomoyo_request_info *r) 35 + { 36 + const char *dev = r->param.mount.dev->name; 37 + const char *dir = r->param.mount.dir->name; 38 + const char *type = r->param.mount.type->name; 39 + const unsigned long flags = r->param.mount.flags; 40 + if (r->granted) 41 + return 0; 42 + if (!strcmp(type, TOMOYO_MOUNT_REMOUNT_KEYWORD)) 43 + tomoyo_warn_log(r, "mount -o remount %s 0x%lX", dir, flags); 44 + else if (!strcmp(type, TOMOYO_MOUNT_BIND_KEYWORD) 45 + || !strcmp(type, TOMOYO_MOUNT_MOVE_KEYWORD)) 46 + tomoyo_warn_log(r, "mount %s %s %s 0x%lX", type, dev, dir, 47 + flags); 48 + else if (!strcmp(type, TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD) || 49 + !strcmp(type, TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD) || 50 + !strcmp(type, TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD) || 51 + !strcmp(type, TOMOYO_MOUNT_MAKE_SHARED_KEYWORD)) 52 + tomoyo_warn_log(r, "mount %s %s 0x%lX", type, dir, flags); 53 + else 54 + tomoyo_warn_log(r, "mount -t %s %s %s 0x%lX", type, dev, dir, 55 + flags); 56 + return tomoyo_supervisor(r, 57 + TOMOYO_KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n", 58 + tomoyo_pattern(r->param.mount.dev), 59 + tomoyo_pattern(r->param.mount.dir), type, 60 + flags); 61 + } 62 + 63 + static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r, 64 + const struct tomoyo_acl_info *ptr) 65 + { 66 + const struct tomoyo_mount_acl *acl = 67 + container_of(ptr, typeof(*acl), head); 68 + return tomoyo_compare_number_union(r->param.mount.flags, &acl->flags) && 69 + tomoyo_compare_name_union(r->param.mount.type, &acl->fs_type) && 70 + tomoyo_compare_name_union(r->param.mount.dir, &acl->dir_name) && 71 + (!r->param.mount.need_dev || 72 + tomoyo_compare_name_union(r->param.mount.dev, &acl->dev_name)); 73 + } 74 + 75 + /** 76 + * tomoyo_mount_acl - Check permission for mount() operation. 77 + * 78 + * @r: Pointer to "struct tomoyo_request_info". 79 + * @dev_name: Name of device file. 80 + * @dir: Pointer to "struct path". 81 + * @type: Name of filesystem type. 82 + * @flags: Mount options. 83 + * 84 + * Returns 0 on success, negative value otherwise. 85 + * 86 + * Caller holds tomoyo_read_lock(). 87 + */ 88 + static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name, 89 + struct path *dir, char *type, unsigned long flags) 90 + { 91 + struct path path; 92 + struct file_system_type *fstype = NULL; 93 + const char *requested_type = NULL; 94 + const char *requested_dir_name = NULL; 95 + const char *requested_dev_name = NULL; 96 + struct tomoyo_path_info rtype; 97 + struct tomoyo_path_info rdev; 98 + struct tomoyo_path_info rdir; 99 + int need_dev = 0; 100 + int error = -ENOMEM; 101 + 102 + /* Get fstype. */ 103 + requested_type = tomoyo_encode(type); 104 + if (!requested_type) 105 + goto out; 106 + rtype.name = requested_type; 107 + tomoyo_fill_path_info(&rtype); 108 + 109 + /* Get mount point. */ 110 + requested_dir_name = tomoyo_realpath_from_path(dir); 111 + if (!requested_dir_name) { 112 + error = -ENOMEM; 113 + goto out; 114 + } 115 + rdir.name = requested_dir_name; 116 + tomoyo_fill_path_info(&rdir); 117 + 118 + /* Compare fs name. */ 119 + if (!strcmp(type, TOMOYO_MOUNT_REMOUNT_KEYWORD)) { 120 + /* dev_name is ignored. */ 121 + } else if (!strcmp(type, TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD) || 122 + !strcmp(type, TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD) || 123 + !strcmp(type, TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD) || 124 + !strcmp(type, TOMOYO_MOUNT_MAKE_SHARED_KEYWORD)) { 125 + /* dev_name is ignored. */ 126 + } else if (!strcmp(type, TOMOYO_MOUNT_BIND_KEYWORD) || 127 + !strcmp(type, TOMOYO_MOUNT_MOVE_KEYWORD)) { 128 + need_dev = -1; /* dev_name is a directory */ 129 + } else { 130 + fstype = get_fs_type(type); 131 + if (!fstype) { 132 + error = -ENODEV; 133 + goto out; 134 + } 135 + if (fstype->fs_flags & FS_REQUIRES_DEV) 136 + /* dev_name is a block device file. */ 137 + need_dev = 1; 138 + } 139 + if (need_dev) { 140 + /* Get mount point or device file. */ 141 + if (kern_path(dev_name, LOOKUP_FOLLOW, &path)) { 142 + error = -ENOENT; 143 + goto out; 144 + } 145 + requested_dev_name = tomoyo_realpath_from_path(&path); 146 + if (!requested_dev_name) { 147 + error = -ENOENT; 148 + goto out; 149 + } 150 + } else { 151 + /* Map dev_name to "<NULL>" if no dev_name given. */ 152 + if (!dev_name) 153 + dev_name = "<NULL>"; 154 + requested_dev_name = tomoyo_encode(dev_name); 155 + if (!requested_dev_name) { 156 + error = -ENOMEM; 157 + goto out; 158 + } 159 + } 160 + rdev.name = requested_dev_name; 161 + tomoyo_fill_path_info(&rdev); 162 + r->param_type = TOMOYO_TYPE_MOUNT_ACL; 163 + r->param.mount.need_dev = need_dev; 164 + r->param.mount.dev = &rdev; 165 + r->param.mount.dir = &rdir; 166 + r->param.mount.type = &rtype; 167 + r->param.mount.flags = flags; 168 + do { 169 + tomoyo_check_acl(r, tomoyo_check_mount_acl); 170 + error = tomoyo_audit_mount_log(r); 171 + } while (error == TOMOYO_RETRY_REQUEST); 172 + out: 173 + kfree(requested_dev_name); 174 + kfree(requested_dir_name); 175 + if (fstype) 176 + put_filesystem(fstype); 177 + kfree(requested_type); 178 + return error; 179 + } 180 + 181 + /** 182 + * tomoyo_mount_permission - Check permission for mount() operation. 183 + * 184 + * @dev_name: Name of device file. 185 + * @path: Pointer to "struct path". 186 + * @type: Name of filesystem type. May be NULL. 187 + * @flags: Mount options. 188 + * @data_page: Optional data. May be NULL. 189 + * 190 + * Returns 0 on success, negative value otherwise. 191 + */ 192 + int tomoyo_mount_permission(char *dev_name, struct path *path, char *type, 193 + unsigned long flags, void *data_page) 194 + { 195 + struct tomoyo_request_info r; 196 + int error; 197 + int idx; 198 + 199 + if (tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_MOUNT) 200 + == TOMOYO_CONFIG_DISABLED) 201 + return 0; 202 + if ((flags & MS_MGC_MSK) == MS_MGC_VAL) 203 + flags &= ~MS_MGC_MSK; 204 + if (flags & MS_REMOUNT) { 205 + type = TOMOYO_MOUNT_REMOUNT_KEYWORD; 206 + flags &= ~MS_REMOUNT; 207 + } 208 + if (flags & MS_MOVE) { 209 + type = TOMOYO_MOUNT_MOVE_KEYWORD; 210 + flags &= ~MS_MOVE; 211 + } 212 + if (flags & MS_BIND) { 213 + type = TOMOYO_MOUNT_BIND_KEYWORD; 214 + flags &= ~MS_BIND; 215 + } 216 + if (flags & MS_UNBINDABLE) { 217 + type = TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD; 218 + flags &= ~MS_UNBINDABLE; 219 + } 220 + if (flags & MS_PRIVATE) { 221 + type = TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD; 222 + flags &= ~MS_PRIVATE; 223 + } 224 + if (flags & MS_SLAVE) { 225 + type = TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD; 226 + flags &= ~MS_SLAVE; 227 + } 228 + if (flags & MS_SHARED) { 229 + type = TOMOYO_MOUNT_MAKE_SHARED_KEYWORD; 230 + flags &= ~MS_SHARED; 231 + } 232 + if (!type) 233 + type = "<NULL>"; 234 + idx = tomoyo_read_lock(); 235 + error = tomoyo_mount_acl(&r, dev_name, path, type, flags); 236 + tomoyo_read_unlock(idx); 237 + return error; 238 + } 239 + 240 + static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a, 241 + const struct tomoyo_acl_info *b) 242 + { 243 + const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head); 244 + const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head); 245 + return tomoyo_same_acl_head(&p1->head, &p2->head) && 246 + tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) && 247 + tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) && 248 + tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) && 249 + tomoyo_same_number_union(&p1->flags, &p2->flags); 250 + } 251 + 252 + /** 253 + * tomoyo_write_mount - Write "struct tomoyo_mount_acl" list. 254 + * 255 + * @data: String to parse. 256 + * @domain: Pointer to "struct tomoyo_domain_info". 257 + * @is_delete: True if it is a delete request. 258 + * 259 + * Returns 0 on success, negative value otherwise. 260 + * 261 + * Caller holds tomoyo_read_lock(). 262 + */ 263 + int tomoyo_write_mount(char *data, struct tomoyo_domain_info *domain, 264 + const bool is_delete) 265 + { 266 + struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL }; 267 + int error = is_delete ? -ENOENT : -ENOMEM; 268 + char *w[4]; 269 + if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[3][0]) 270 + return -EINVAL; 271 + if (!tomoyo_parse_name_union(w[0], &e.dev_name) || 272 + !tomoyo_parse_name_union(w[1], &e.dir_name) || 273 + !tomoyo_parse_name_union(w[2], &e.fs_type) || 274 + !tomoyo_parse_number_union(w[3], &e.flags)) 275 + goto out; 276 + error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, 277 + tomoyo_same_mount_acl, NULL); 278 + out: 279 + tomoyo_put_name_union(&e.dev_name); 280 + tomoyo_put_name_union(&e.dir_name); 281 + tomoyo_put_name_union(&e.fs_type); 282 + tomoyo_put_number_union(&e.flags); 283 + return error; 284 + }
-172
security/tomoyo/path_group.c
··· 1 - /* 2 - * security/tomoyo/path_group.c 3 - * 4 - * Copyright (C) 2005-2009 NTT DATA CORPORATION 5 - */ 6 - 7 - #include <linux/slab.h> 8 - #include "common.h" 9 - /* The list for "struct ccs_path_group". */ 10 - LIST_HEAD(tomoyo_path_group_list); 11 - 12 - /** 13 - * tomoyo_get_path_group - Allocate memory for "struct tomoyo_path_group". 14 - * 15 - * @group_name: The name of pathname group. 16 - * 17 - * Returns pointer to "struct tomoyo_path_group" on success, NULL otherwise. 18 - */ 19 - struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name) 20 - { 21 - struct tomoyo_path_group *entry = NULL; 22 - struct tomoyo_path_group *group = NULL; 23 - const struct tomoyo_path_info *saved_group_name; 24 - int error = -ENOMEM; 25 - if (!tomoyo_is_correct_path(group_name, 0, 0, 0) || 26 - !group_name[0]) 27 - return NULL; 28 - saved_group_name = tomoyo_get_name(group_name); 29 - if (!saved_group_name) 30 - return NULL; 31 - entry = kzalloc(sizeof(*entry), GFP_NOFS); 32 - if (mutex_lock_interruptible(&tomoyo_policy_lock)) 33 - goto out; 34 - list_for_each_entry_rcu(group, &tomoyo_path_group_list, list) { 35 - if (saved_group_name != group->group_name) 36 - continue; 37 - atomic_inc(&group->users); 38 - error = 0; 39 - break; 40 - } 41 - if (error && tomoyo_memory_ok(entry)) { 42 - INIT_LIST_HEAD(&entry->member_list); 43 - entry->group_name = saved_group_name; 44 - saved_group_name = NULL; 45 - atomic_set(&entry->users, 1); 46 - list_add_tail_rcu(&entry->list, &tomoyo_path_group_list); 47 - group = entry; 48 - entry = NULL; 49 - error = 0; 50 - } 51 - mutex_unlock(&tomoyo_policy_lock); 52 - out: 53 - tomoyo_put_name(saved_group_name); 54 - kfree(entry); 55 - return !error ? group : NULL; 56 - } 57 - 58 - /** 59 - * tomoyo_write_path_group_policy - Write "struct tomoyo_path_group" list. 60 - * 61 - * @data: String to parse. 62 - * @is_delete: True if it is a delete request. 63 - * 64 - * Returns 0 on success, nagative value otherwise. 65 - */ 66 - int tomoyo_write_path_group_policy(char *data, const bool is_delete) 67 - { 68 - struct tomoyo_path_group *group; 69 - struct tomoyo_path_group_member *member; 70 - struct tomoyo_path_group_member e = { }; 71 - int error = is_delete ? -ENOENT : -ENOMEM; 72 - char *w[2]; 73 - if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0]) 74 - return -EINVAL; 75 - group = tomoyo_get_path_group(w[0]); 76 - if (!group) 77 - return -ENOMEM; 78 - e.member_name = tomoyo_get_name(w[1]); 79 - if (!e.member_name) 80 - goto out; 81 - if (mutex_lock_interruptible(&tomoyo_policy_lock)) 82 - goto out; 83 - list_for_each_entry_rcu(member, &group->member_list, list) { 84 - if (member->member_name != e.member_name) 85 - continue; 86 - member->is_deleted = is_delete; 87 - error = 0; 88 - break; 89 - } 90 - if (!is_delete && error) { 91 - struct tomoyo_path_group_member *entry = 92 - tomoyo_commit_ok(&e, sizeof(e)); 93 - if (entry) { 94 - list_add_tail_rcu(&entry->list, &group->member_list); 95 - error = 0; 96 - } 97 - } 98 - mutex_unlock(&tomoyo_policy_lock); 99 - out: 100 - tomoyo_put_name(e.member_name); 101 - tomoyo_put_path_group(group); 102 - return error; 103 - } 104 - 105 - /** 106 - * tomoyo_read_path_group_policy - Read "struct tomoyo_path_group" list. 107 - * 108 - * @head: Pointer to "struct tomoyo_io_buffer". 109 - * 110 - * Returns true on success, false otherwise. 111 - * 112 - * Caller holds tomoyo_read_lock(). 113 - */ 114 - bool tomoyo_read_path_group_policy(struct tomoyo_io_buffer *head) 115 - { 116 - struct list_head *gpos; 117 - struct list_head *mpos; 118 - list_for_each_cookie(gpos, head->read_var1, &tomoyo_path_group_list) { 119 - struct tomoyo_path_group *group; 120 - group = list_entry(gpos, struct tomoyo_path_group, list); 121 - list_for_each_cookie(mpos, head->read_var2, 122 - &group->member_list) { 123 - struct tomoyo_path_group_member *member; 124 - member = list_entry(mpos, 125 - struct tomoyo_path_group_member, 126 - list); 127 - if (member->is_deleted) 128 - continue; 129 - if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_PATH_GROUP 130 - "%s %s\n", 131 - group->group_name->name, 132 - member->member_name->name)) 133 - return false; 134 - } 135 - } 136 - return true; 137 - } 138 - 139 - /** 140 - * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group. 141 - * 142 - * @pathname: The name of pathname. 143 - * @group: Pointer to "struct tomoyo_path_group". 144 - * @may_use_pattern: True if wild card is permitted. 145 - * 146 - * Returns true if @pathname matches pathnames in @group, false otherwise. 147 - * 148 - * Caller holds tomoyo_read_lock(). 149 - */ 150 - bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, 151 - const struct tomoyo_path_group *group, 152 - const bool may_use_pattern) 153 - { 154 - struct tomoyo_path_group_member *member; 155 - bool matched = false; 156 - list_for_each_entry_rcu(member, &group->member_list, list) { 157 - if (member->is_deleted) 158 - continue; 159 - if (!member->member_name->is_patterned) { 160 - if (tomoyo_pathcmp(pathname, member->member_name)) 161 - continue; 162 - } else if (may_use_pattern) { 163 - if (!tomoyo_path_matches_pattern(pathname, 164 - member->member_name)) 165 - continue; 166 - } else 167 - continue; 168 - matched = true; 169 - break; 170 - } 171 - return matched; 172 - }
+120 -318
security/tomoyo/realpath.c
··· 1 1 /* 2 2 * security/tomoyo/realpath.c 3 3 * 4 - * Get the canonicalized absolute pathnames. The basis for TOMOYO. 4 + * Pathname calculation functions for TOMOYO. 5 5 * 6 - * Copyright (C) 2005-2009 NTT DATA CORPORATION 7 - * 8 - * Version: 2.2.0 2009/04/01 9 - * 6 + * Copyright (C) 2005-2010 NTT DATA CORPORATION 10 7 */ 11 8 12 9 #include <linux/types.h> 13 10 #include <linux/mount.h> 14 11 #include <linux/mnt_namespace.h> 15 12 #include <linux/fs_struct.h> 16 - #include <linux/hash.h> 17 13 #include <linux/magic.h> 18 14 #include <linux/slab.h> 15 + #include <net/sock.h> 19 16 #include "common.h" 20 17 21 18 /** 22 19 * tomoyo_encode: Convert binary string to ascii string. 23 20 * 24 - * @buffer: Buffer for ASCII string. 25 - * @buflen: Size of @buffer. 26 - * @str: Binary string. 21 + * @str: String in binary format. 27 22 * 28 - * Returns 0 on success, -ENOMEM otherwise. 23 + * Returns pointer to @str in ascii format on success, NULL otherwise. 24 + * 25 + * This function uses kzalloc(), so caller must kfree() if this function 26 + * didn't return NULL. 29 27 */ 30 - int tomoyo_encode(char *buffer, int buflen, const char *str) 28 + char *tomoyo_encode(const char *str) 31 29 { 32 - while (1) { 33 - const unsigned char c = *(unsigned char *) str++; 30 + int len = 0; 31 + const char *p = str; 32 + char *cp; 33 + char *cp0; 34 34 35 - if (tomoyo_is_valid(c)) { 36 - if (--buflen <= 0) 37 - break; 38 - *buffer++ = (char) c; 39 - if (c != '\\') 40 - continue; 41 - if (--buflen <= 0) 42 - break; 43 - *buffer++ = (char) c; 44 - continue; 45 - } 46 - if (!c) { 47 - if (--buflen <= 0) 48 - break; 49 - *buffer = '\0'; 50 - return 0; 51 - } 52 - buflen -= 4; 53 - if (buflen <= 0) 54 - break; 55 - *buffer++ = '\\'; 56 - *buffer++ = (c >> 6) + '0'; 57 - *buffer++ = ((c >> 3) & 7) + '0'; 58 - *buffer++ = (c & 7) + '0'; 35 + if (!p) 36 + return NULL; 37 + while (*p) { 38 + const unsigned char c = *p++; 39 + if (c == '\\') 40 + len += 2; 41 + else if (c > ' ' && c < 127) 42 + len++; 43 + else 44 + len += 4; 59 45 } 60 - return -ENOMEM; 61 - } 46 + len++; 47 + /* Reserve space for appending "/". */ 48 + cp = kzalloc(len + 10, GFP_NOFS); 49 + if (!cp) 50 + return NULL; 51 + cp0 = cp; 52 + p = str; 53 + while (*p) { 54 + const unsigned char c = *p++; 62 55 63 - /** 64 - * tomoyo_realpath_from_path2 - Returns realpath(3) of the given dentry but ignores chroot'ed root. 65 - * 66 - * @path: Pointer to "struct path". 67 - * @newname: Pointer to buffer to return value in. 68 - * @newname_len: Size of @newname. 69 - * 70 - * Returns 0 on success, negative value otherwise. 71 - * 72 - * If dentry is a directory, trailing '/' is appended. 73 - * Characters out of 0x20 < c < 0x7F range are converted to 74 - * \ooo style octal string. 75 - * Character \ is converted to \\ string. 76 - */ 77 - int tomoyo_realpath_from_path2(struct path *path, char *newname, 78 - int newname_len) 79 - { 80 - int error = -ENOMEM; 81 - struct dentry *dentry = path->dentry; 82 - char *sp; 83 - 84 - if (!dentry || !path->mnt || !newname || newname_len <= 2048) 85 - return -EINVAL; 86 - if (dentry->d_op && dentry->d_op->d_dname) { 87 - /* For "socket:[\$]" and "pipe:[\$]". */ 88 - static const int offset = 1536; 89 - sp = dentry->d_op->d_dname(dentry, newname + offset, 90 - newname_len - offset); 91 - } else { 92 - struct path ns_root = {.mnt = NULL, .dentry = NULL}; 93 - 94 - spin_lock(&dcache_lock); 95 - /* go to whatever namespace root we are under */ 96 - sp = __d_path(path, &ns_root, newname, newname_len); 97 - spin_unlock(&dcache_lock); 98 - /* Prepend "/proc" prefix if using internal proc vfs mount. */ 99 - if (!IS_ERR(sp) && (path->mnt->mnt_flags & MNT_INTERNAL) && 100 - (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) { 101 - sp -= 5; 102 - if (sp >= newname) 103 - memcpy(sp, "/proc", 5); 104 - else 105 - sp = ERR_PTR(-ENOMEM); 56 + if (c == '\\') { 57 + *cp++ = '\\'; 58 + *cp++ = '\\'; 59 + } else if (c > ' ' && c < 127) { 60 + *cp++ = c; 61 + } else { 62 + *cp++ = '\\'; 63 + *cp++ = (c >> 6) + '0'; 64 + *cp++ = ((c >> 3) & 7) + '0'; 65 + *cp++ = (c & 7) + '0'; 106 66 } 107 67 } 108 - if (IS_ERR(sp)) 109 - error = PTR_ERR(sp); 110 - else 111 - error = tomoyo_encode(newname, sp - newname, sp); 112 - /* Append trailing '/' if dentry is a directory. */ 113 - if (!error && dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode) 114 - && *newname) { 115 - sp = newname + strlen(newname); 116 - if (*(sp - 1) != '/') { 117 - if (sp < newname + newname_len - 4) { 118 - *sp++ = '/'; 119 - *sp = '\0'; 120 - } else { 121 - error = -ENOMEM; 122 - } 123 - } 124 - } 125 - if (error) 126 - printk(KERN_WARNING "tomoyo_realpath: Pathname too long.\n"); 127 - return error; 68 + return cp0; 128 69 } 129 70 130 71 /** ··· 75 134 * 76 135 * Returns the realpath of the given @path on success, NULL otherwise. 77 136 * 137 + * If dentry is a directory, trailing '/' is appended. 138 + * Characters out of 0x20 < c < 0x7F range are converted to 139 + * \ooo style octal string. 140 + * Character \ is converted to \\ string. 141 + * 78 142 * These functions use kzalloc(), so the caller must call kfree() 79 143 * if these functions didn't return NULL. 80 144 */ 81 145 char *tomoyo_realpath_from_path(struct path *path) 82 146 { 83 - char *buf = kzalloc(sizeof(struct tomoyo_page_buffer), GFP_NOFS); 84 - 85 - BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer) 86 - <= TOMOYO_MAX_PATHNAME_LEN - 1); 87 - if (!buf) 147 + char *buf = NULL; 148 + char *name = NULL; 149 + unsigned int buf_len = PAGE_SIZE / 2; 150 + struct dentry *dentry = path->dentry; 151 + bool is_dir; 152 + if (!dentry) 88 153 return NULL; 89 - if (tomoyo_realpath_from_path2(path, buf, 90 - TOMOYO_MAX_PATHNAME_LEN - 1) == 0) 91 - return buf; 92 - kfree(buf); 93 - return NULL; 94 - } 95 - 96 - /** 97 - * tomoyo_realpath - Get realpath of a pathname. 98 - * 99 - * @pathname: The pathname to solve. 100 - * 101 - * Returns the realpath of @pathname on success, NULL otherwise. 102 - */ 103 - char *tomoyo_realpath(const char *pathname) 104 - { 105 - struct path path; 106 - 107 - if (pathname && kern_path(pathname, LOOKUP_FOLLOW, &path) == 0) { 108 - char *buf = tomoyo_realpath_from_path(&path); 109 - path_put(&path); 110 - return buf; 154 + is_dir = dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode); 155 + while (1) { 156 + struct path ns_root = { .mnt = NULL, .dentry = NULL }; 157 + char *pos; 158 + buf_len <<= 1; 159 + kfree(buf); 160 + buf = kmalloc(buf_len, GFP_NOFS); 161 + if (!buf) 162 + break; 163 + /* Get better name for socket. */ 164 + if (dentry->d_sb && dentry->d_sb->s_magic == SOCKFS_MAGIC) { 165 + struct inode *inode = dentry->d_inode; 166 + struct socket *sock = inode ? SOCKET_I(inode) : NULL; 167 + struct sock *sk = sock ? sock->sk : NULL; 168 + if (sk) { 169 + snprintf(buf, buf_len - 1, "socket:[family=%u:" 170 + "type=%u:protocol=%u]", sk->sk_family, 171 + sk->sk_type, sk->sk_protocol); 172 + } else { 173 + snprintf(buf, buf_len - 1, "socket:[unknown]"); 174 + } 175 + name = tomoyo_encode(buf); 176 + break; 177 + } 178 + /* For "socket:[\$]" and "pipe:[\$]". */ 179 + if (dentry->d_op && dentry->d_op->d_dname) { 180 + pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1); 181 + if (IS_ERR(pos)) 182 + continue; 183 + name = tomoyo_encode(pos); 184 + break; 185 + } 186 + /* If we don't have a vfsmount, we can't calculate. */ 187 + if (!path->mnt) 188 + break; 189 + spin_lock(&dcache_lock); 190 + /* go to whatever namespace root we are under */ 191 + pos = __d_path(path, &ns_root, buf, buf_len); 192 + spin_unlock(&dcache_lock); 193 + /* Prepend "/proc" prefix if using internal proc vfs mount. */ 194 + if (!IS_ERR(pos) && (path->mnt->mnt_flags & MNT_INTERNAL) && 195 + (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) { 196 + pos -= 5; 197 + if (pos >= buf) 198 + memcpy(pos, "/proc", 5); 199 + else 200 + pos = ERR_PTR(-ENOMEM); 201 + } 202 + if (IS_ERR(pos)) 203 + continue; 204 + name = tomoyo_encode(pos); 205 + break; 111 206 } 112 - return NULL; 207 + kfree(buf); 208 + if (!name) 209 + tomoyo_warn_oom(__func__); 210 + else if (is_dir && *name) { 211 + /* Append trailing '/' if dentry is a directory. */ 212 + char *pos = name + strlen(name) - 1; 213 + if (*pos != '/') 214 + /* 215 + * This is OK because tomoyo_encode() reserves space 216 + * for appending "/". 217 + */ 218 + *++pos = '/'; 219 + } 220 + return name; 113 221 } 114 222 115 223 /** ··· 178 188 return buf; 179 189 } 180 190 return NULL; 181 - } 182 - 183 - /* Memory allocated for non-string data. */ 184 - static atomic_t tomoyo_policy_memory_size; 185 - /* Quota for holding policy. */ 186 - static unsigned int tomoyo_quota_for_policy; 187 - 188 - /** 189 - * tomoyo_memory_ok - Check memory quota. 190 - * 191 - * @ptr: Pointer to allocated memory. 192 - * 193 - * Returns true on success, false otherwise. 194 - * 195 - * Caller holds tomoyo_policy_lock. 196 - * Memory pointed by @ptr will be zeroed on success. 197 - */ 198 - bool tomoyo_memory_ok(void *ptr) 199 - { 200 - int allocated_len = ptr ? ksize(ptr) : 0; 201 - atomic_add(allocated_len, &tomoyo_policy_memory_size); 202 - if (ptr && (!tomoyo_quota_for_policy || 203 - atomic_read(&tomoyo_policy_memory_size) 204 - <= tomoyo_quota_for_policy)) { 205 - memset(ptr, 0, allocated_len); 206 - return true; 207 - } 208 - printk(KERN_WARNING "ERROR: Out of memory " 209 - "for tomoyo_alloc_element().\n"); 210 - if (!tomoyo_policy_loaded) 211 - panic("MAC Initialization failed.\n"); 212 - return false; 213 - } 214 - 215 - /** 216 - * tomoyo_commit_ok - Check memory quota. 217 - * 218 - * @data: Data to copy from. 219 - * @size: Size in byte. 220 - * 221 - * Returns pointer to allocated memory on success, NULL otherwise. 222 - */ 223 - void *tomoyo_commit_ok(void *data, const unsigned int size) 224 - { 225 - void *ptr = kzalloc(size, GFP_NOFS); 226 - if (tomoyo_memory_ok(ptr)) { 227 - memmove(ptr, data, size); 228 - memset(data, 0, size); 229 - return ptr; 230 - } 231 - return NULL; 232 - } 233 - 234 - /** 235 - * tomoyo_memory_free - Free memory for elements. 236 - * 237 - * @ptr: Pointer to allocated memory. 238 - */ 239 - void tomoyo_memory_free(void *ptr) 240 - { 241 - atomic_sub(ksize(ptr), &tomoyo_policy_memory_size); 242 - kfree(ptr); 243 - } 244 - 245 - /* 246 - * tomoyo_name_list is used for holding string data used by TOMOYO. 247 - * Since same string data is likely used for multiple times (e.g. 248 - * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of 249 - * "const struct tomoyo_path_info *". 250 - */ 251 - struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; 252 - 253 - /** 254 - * tomoyo_get_name - Allocate permanent memory for string data. 255 - * 256 - * @name: The string to store into the permernent memory. 257 - * 258 - * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. 259 - */ 260 - const struct tomoyo_path_info *tomoyo_get_name(const char *name) 261 - { 262 - struct tomoyo_name_entry *ptr; 263 - unsigned int hash; 264 - int len; 265 - int allocated_len; 266 - struct list_head *head; 267 - 268 - if (!name) 269 - return NULL; 270 - len = strlen(name) + 1; 271 - hash = full_name_hash((const unsigned char *) name, len - 1); 272 - head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; 273 - if (mutex_lock_interruptible(&tomoyo_policy_lock)) 274 - return NULL; 275 - list_for_each_entry(ptr, head, list) { 276 - if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) 277 - continue; 278 - atomic_inc(&ptr->users); 279 - goto out; 280 - } 281 - ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS); 282 - allocated_len = ptr ? ksize(ptr) : 0; 283 - if (!ptr || (tomoyo_quota_for_policy && 284 - atomic_read(&tomoyo_policy_memory_size) + allocated_len 285 - > tomoyo_quota_for_policy)) { 286 - kfree(ptr); 287 - printk(KERN_WARNING "ERROR: Out of memory " 288 - "for tomoyo_get_name().\n"); 289 - if (!tomoyo_policy_loaded) 290 - panic("MAC Initialization failed.\n"); 291 - ptr = NULL; 292 - goto out; 293 - } 294 - atomic_add(allocated_len, &tomoyo_policy_memory_size); 295 - ptr->entry.name = ((char *) ptr) + sizeof(*ptr); 296 - memmove((char *) ptr->entry.name, name, len); 297 - atomic_set(&ptr->users, 1); 298 - tomoyo_fill_path_info(&ptr->entry); 299 - list_add_tail(&ptr->list, head); 300 - out: 301 - mutex_unlock(&tomoyo_policy_lock); 302 - return ptr ? &ptr->entry : NULL; 303 - } 304 - 305 - /** 306 - * tomoyo_realpath_init - Initialize realpath related code. 307 - */ 308 - void __init tomoyo_realpath_init(void) 309 - { 310 - int i; 311 - 312 - BUILD_BUG_ON(TOMOYO_MAX_PATHNAME_LEN > PATH_MAX); 313 - for (i = 0; i < TOMOYO_MAX_HASH; i++) 314 - INIT_LIST_HEAD(&tomoyo_name_list[i]); 315 - INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); 316 - tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME); 317 - /* 318 - * tomoyo_read_lock() is not needed because this function is 319 - * called before the first "delete" request. 320 - */ 321 - list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list); 322 - if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain) 323 - panic("Can't register tomoyo_kernel_domain"); 324 - } 325 - 326 - /** 327 - * tomoyo_read_memory_counter - Check for memory usage in bytes. 328 - * 329 - * @head: Pointer to "struct tomoyo_io_buffer". 330 - * 331 - * Returns memory usage. 332 - */ 333 - int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head) 334 - { 335 - if (!head->read_eof) { 336 - const unsigned int policy 337 - = atomic_read(&tomoyo_policy_memory_size); 338 - char buffer[64]; 339 - 340 - memset(buffer, 0, sizeof(buffer)); 341 - if (tomoyo_quota_for_policy) 342 - snprintf(buffer, sizeof(buffer) - 1, 343 - " (Quota: %10u)", 344 - tomoyo_quota_for_policy); 345 - else 346 - buffer[0] = '\0'; 347 - tomoyo_io_printf(head, "Policy: %10u%s\n", policy, buffer); 348 - tomoyo_io_printf(head, "Total: %10u\n", policy); 349 - head->read_eof = true; 350 - } 351 - return 0; 352 - } 353 - 354 - /** 355 - * tomoyo_write_memory_quota - Set memory quota. 356 - * 357 - * @head: Pointer to "struct tomoyo_io_buffer". 358 - * 359 - * Returns 0. 360 - */ 361 - int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head) 362 - { 363 - char *data = head->write_buf; 364 - unsigned int size; 365 - 366 - if (sscanf(data, "Policy: %u", &size) == 1) 367 - tomoyo_quota_for_policy = size; 368 - return 0; 369 191 }
+155
security/tomoyo/securityfs_if.c
··· 1 + /* 2 + * security/tomoyo/common.c 3 + * 4 + * Securityfs interface for TOMOYO. 5 + * 6 + * Copyright (C) 2005-2010 NTT DATA CORPORATION 7 + */ 8 + 9 + #include <linux/security.h> 10 + #include "common.h" 11 + 12 + /** 13 + * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface. 14 + * 15 + * @inode: Pointer to "struct inode". 16 + * @file: Pointer to "struct file". 17 + * 18 + * Returns 0 on success, negative value otherwise. 19 + */ 20 + static int tomoyo_open(struct inode *inode, struct file *file) 21 + { 22 + const int key = ((u8 *) file->f_path.dentry->d_inode->i_private) 23 + - ((u8 *) NULL); 24 + return tomoyo_open_control(key, file); 25 + } 26 + 27 + /** 28 + * tomoyo_release - close() for /sys/kernel/security/tomoyo/ interface. 29 + * 30 + * @inode: Pointer to "struct inode". 31 + * @file: Pointer to "struct file". 32 + * 33 + * Returns 0 on success, negative value otherwise. 34 + */ 35 + static int tomoyo_release(struct inode *inode, struct file *file) 36 + { 37 + return tomoyo_close_control(file); 38 + } 39 + 40 + /** 41 + * tomoyo_poll - poll() for /proc/ccs/ interface. 42 + * 43 + * @file: Pointer to "struct file". 44 + * @wait: Pointer to "poll_table". 45 + * 46 + * Returns 0 on success, negative value otherwise. 47 + */ 48 + static unsigned int tomoyo_poll(struct file *file, poll_table *wait) 49 + { 50 + return tomoyo_poll_control(file, wait); 51 + } 52 + 53 + /** 54 + * tomoyo_read - read() for /sys/kernel/security/tomoyo/ interface. 55 + * 56 + * @file: Pointer to "struct file". 57 + * @buf: Pointer to buffer. 58 + * @count: Size of @buf. 59 + * @ppos: Unused. 60 + * 61 + * Returns bytes read on success, negative value otherwise. 62 + */ 63 + static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count, 64 + loff_t *ppos) 65 + { 66 + return tomoyo_read_control(file, buf, count); 67 + } 68 + 69 + /** 70 + * tomoyo_write - write() for /sys/kernel/security/tomoyo/ interface. 71 + * 72 + * @file: Pointer to "struct file". 73 + * @buf: Pointer to buffer. 74 + * @count: Size of @buf. 75 + * @ppos: Unused. 76 + * 77 + * Returns @count on success, negative value otherwise. 78 + */ 79 + static ssize_t tomoyo_write(struct file *file, const char __user *buf, 80 + size_t count, loff_t *ppos) 81 + { 82 + return tomoyo_write_control(file, buf, count); 83 + } 84 + 85 + /* 86 + * tomoyo_operations is a "struct file_operations" which is used for handling 87 + * /sys/kernel/security/tomoyo/ interface. 88 + * 89 + * Some files under /sys/kernel/security/tomoyo/ directory accept open(O_RDWR). 90 + * See tomoyo_io_buffer for internals. 91 + */ 92 + static const struct file_operations tomoyo_operations = { 93 + .open = tomoyo_open, 94 + .release = tomoyo_release, 95 + .poll = tomoyo_poll, 96 + .read = tomoyo_read, 97 + .write = tomoyo_write, 98 + .llseek = noop_llseek, 99 + }; 100 + 101 + /** 102 + * tomoyo_create_entry - Create interface files under /sys/kernel/security/tomoyo/ directory. 103 + * 104 + * @name: The name of the interface file. 105 + * @mode: The permission of the interface file. 106 + * @parent: The parent directory. 107 + * @key: Type of interface. 108 + * 109 + * Returns nothing. 110 + */ 111 + static void __init tomoyo_create_entry(const char *name, const mode_t mode, 112 + struct dentry *parent, const u8 key) 113 + { 114 + securityfs_create_file(name, mode, parent, ((u8 *) NULL) + key, 115 + &tomoyo_operations); 116 + } 117 + 118 + /** 119 + * tomoyo_initerface_init - Initialize /sys/kernel/security/tomoyo/ interface. 120 + * 121 + * Returns 0. 122 + */ 123 + static int __init tomoyo_initerface_init(void) 124 + { 125 + struct dentry *tomoyo_dir; 126 + 127 + /* Don't create securityfs entries unless registered. */ 128 + if (current_cred()->security != &tomoyo_kernel_domain) 129 + return 0; 130 + 131 + tomoyo_dir = securityfs_create_dir("tomoyo", NULL); 132 + tomoyo_create_entry("query", 0600, tomoyo_dir, 133 + TOMOYO_QUERY); 134 + tomoyo_create_entry("domain_policy", 0600, tomoyo_dir, 135 + TOMOYO_DOMAINPOLICY); 136 + tomoyo_create_entry("exception_policy", 0600, tomoyo_dir, 137 + TOMOYO_EXCEPTIONPOLICY); 138 + tomoyo_create_entry("self_domain", 0400, tomoyo_dir, 139 + TOMOYO_SELFDOMAIN); 140 + tomoyo_create_entry(".domain_status", 0600, tomoyo_dir, 141 + TOMOYO_DOMAIN_STATUS); 142 + tomoyo_create_entry(".process_status", 0600, tomoyo_dir, 143 + TOMOYO_PROCESS_STATUS); 144 + tomoyo_create_entry("meminfo", 0600, tomoyo_dir, 145 + TOMOYO_MEMINFO); 146 + tomoyo_create_entry("profile", 0600, tomoyo_dir, 147 + TOMOYO_PROFILE); 148 + tomoyo_create_entry("manager", 0600, tomoyo_dir, 149 + TOMOYO_MANAGER); 150 + tomoyo_create_entry("version", 0400, tomoyo_dir, 151 + TOMOYO_VERSION); 152 + return 0; 153 + } 154 + 155 + fs_initcall(tomoyo_initerface_init);
+20 -15
security/tomoyo/tomoyo.c
··· 3 3 * 4 4 * LSM hooks for TOMOYO Linux. 5 5 * 6 - * Copyright (C) 2005-2009 NTT DATA CORPORATION 7 - * 8 - * Version: 2.2.0 2009/04/01 9 - * 6 + * Copyright (C) 2005-2010 NTT DATA CORPORATION 10 7 */ 11 8 12 9 #include <linux/security.h> ··· 93 96 return tomoyo_check_open_permission(domain, &bprm->file->f_path, O_RDONLY); 94 97 } 95 98 96 - static int tomoyo_path_truncate(struct path *path, loff_t length, 97 - unsigned int time_attrs) 99 + static int tomoyo_path_truncate(struct path *path) 98 100 { 99 101 return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path); 100 102 } ··· 108 112 int mode) 109 113 { 110 114 struct path path = { parent->mnt, dentry }; 111 - return tomoyo_path_perm(TOMOYO_TYPE_MKDIR, &path); 115 + return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path, 116 + mode & S_IALLUGO); 112 117 } 113 118 114 119 static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) ··· 130 133 { 131 134 struct path path = { parent->mnt, dentry }; 132 135 int type = TOMOYO_TYPE_CREATE; 136 + const unsigned int perm = mode & S_IALLUGO; 133 137 134 138 switch (mode & S_IFMT) { 135 139 case S_IFCHR: ··· 139 141 case S_IFBLK: 140 142 type = TOMOYO_TYPE_MKBLOCK; 141 143 break; 144 + default: 145 + goto no_dev; 146 + } 147 + return tomoyo_mkdev_perm(type, &path, perm, dev); 148 + no_dev: 149 + switch (mode & S_IFMT) { 142 150 case S_IFIFO: 143 151 type = TOMOYO_TYPE_MKFIFO; 144 152 break; ··· 152 148 type = TOMOYO_TYPE_MKSOCK; 153 149 break; 154 150 } 155 - return tomoyo_path_perm(type, &path); 151 + return tomoyo_path_number_perm(type, &path, perm); 156 152 } 157 153 158 154 static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, ··· 177 173 unsigned long arg) 178 174 { 179 175 if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)) 180 - return tomoyo_check_rewrite_permission(file); 176 + return tomoyo_path_perm(TOMOYO_TYPE_REWRITE, &file->f_path); 181 177 return 0; 182 178 } 183 179 ··· 193 189 static int tomoyo_file_ioctl(struct file *file, unsigned int cmd, 194 190 unsigned long arg) 195 191 { 196 - return tomoyo_path_perm(TOMOYO_TYPE_IOCTL, &file->f_path); 192 + return tomoyo_path_number_perm(TOMOYO_TYPE_IOCTL, &file->f_path, cmd); 197 193 } 198 194 199 195 static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt, 200 196 mode_t mode) 201 197 { 202 198 struct path path = { mnt, dentry }; 203 - return tomoyo_path_perm(TOMOYO_TYPE_CHMOD, &path); 199 + return tomoyo_path_number_perm(TOMOYO_TYPE_CHMOD, &path, 200 + mode & S_IALLUGO); 204 201 } 205 202 206 203 static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid) 207 204 { 208 205 int error = 0; 209 206 if (uid != (uid_t) -1) 210 - error = tomoyo_path_perm(TOMOYO_TYPE_CHOWN, path); 207 + error = tomoyo_path_number_perm(TOMOYO_TYPE_CHOWN, path, uid); 211 208 if (!error && gid != (gid_t) -1) 212 - error = tomoyo_path_perm(TOMOYO_TYPE_CHGRP, path); 209 + error = tomoyo_path_number_perm(TOMOYO_TYPE_CHGRP, path, gid); 213 210 return error; 214 211 } 215 212 ··· 222 217 static int tomoyo_sb_mount(char *dev_name, struct path *path, 223 218 char *type, unsigned long flags, void *data) 224 219 { 225 - return tomoyo_path_perm(TOMOYO_TYPE_MOUNT, path); 220 + return tomoyo_mount_permission(dev_name, path, type, flags, data); 226 221 } 227 222 228 223 static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) ··· 282 277 panic("Failure registering TOMOYO Linux"); 283 278 printk(KERN_INFO "TOMOYO Linux initialized\n"); 284 279 cred->security = &tomoyo_kernel_domain; 285 - tomoyo_realpath_init(); 280 + tomoyo_mm_init(); 286 281 return 0; 287 282 } 288 283
+963
security/tomoyo/util.c
··· 1 + /* 2 + * security/tomoyo/util.c 3 + * 4 + * Utility functions for TOMOYO. 5 + * 6 + * Copyright (C) 2005-2010 NTT DATA CORPORATION 7 + */ 8 + 9 + #include <linux/slab.h> 10 + #include "common.h" 11 + 12 + /* Lock for protecting policy. */ 13 + DEFINE_MUTEX(tomoyo_policy_lock); 14 + 15 + /* Has /sbin/init started? */ 16 + bool tomoyo_policy_loaded; 17 + 18 + /** 19 + * tomoyo_parse_ulong - Parse an "unsigned long" value. 20 + * 21 + * @result: Pointer to "unsigned long". 22 + * @str: Pointer to string to parse. 23 + * 24 + * Returns value type on success, 0 otherwise. 25 + * 26 + * The @src is updated to point the first character after the value 27 + * on success. 28 + */ 29 + static u8 tomoyo_parse_ulong(unsigned long *result, char **str) 30 + { 31 + const char *cp = *str; 32 + char *ep; 33 + int base = 10; 34 + if (*cp == '0') { 35 + char c = *(cp + 1); 36 + if (c == 'x' || c == 'X') { 37 + base = 16; 38 + cp += 2; 39 + } else if (c >= '0' && c <= '7') { 40 + base = 8; 41 + cp++; 42 + } 43 + } 44 + *result = simple_strtoul(cp, &ep, base); 45 + if (cp == ep) 46 + return 0; 47 + *str = ep; 48 + switch (base) { 49 + case 16: 50 + return TOMOYO_VALUE_TYPE_HEXADECIMAL; 51 + case 8: 52 + return TOMOYO_VALUE_TYPE_OCTAL; 53 + default: 54 + return TOMOYO_VALUE_TYPE_DECIMAL; 55 + } 56 + } 57 + 58 + /** 59 + * tomoyo_print_ulong - Print an "unsigned long" value. 60 + * 61 + * @buffer: Pointer to buffer. 62 + * @buffer_len: Size of @buffer. 63 + * @value: An "unsigned long" value. 64 + * @type: Type of @value. 65 + * 66 + * Returns nothing. 67 + */ 68 + void tomoyo_print_ulong(char *buffer, const int buffer_len, 69 + const unsigned long value, const u8 type) 70 + { 71 + if (type == TOMOYO_VALUE_TYPE_DECIMAL) 72 + snprintf(buffer, buffer_len, "%lu", value); 73 + else if (type == TOMOYO_VALUE_TYPE_OCTAL) 74 + snprintf(buffer, buffer_len, "0%lo", value); 75 + else if (type == TOMOYO_VALUE_TYPE_HEXADECIMAL) 76 + snprintf(buffer, buffer_len, "0x%lX", value); 77 + else 78 + snprintf(buffer, buffer_len, "type(%u)", type); 79 + } 80 + 81 + /** 82 + * tomoyo_parse_name_union - Parse a tomoyo_name_union. 83 + * 84 + * @filename: Name or name group. 85 + * @ptr: Pointer to "struct tomoyo_name_union". 86 + * 87 + * Returns true on success, false otherwise. 88 + */ 89 + bool tomoyo_parse_name_union(const char *filename, 90 + struct tomoyo_name_union *ptr) 91 + { 92 + if (!tomoyo_correct_word(filename)) 93 + return false; 94 + if (filename[0] == '@') { 95 + ptr->group = tomoyo_get_group(filename + 1, TOMOYO_PATH_GROUP); 96 + ptr->is_group = true; 97 + return ptr->group != NULL; 98 + } 99 + ptr->filename = tomoyo_get_name(filename); 100 + ptr->is_group = false; 101 + return ptr->filename != NULL; 102 + } 103 + 104 + /** 105 + * tomoyo_parse_number_union - Parse a tomoyo_number_union. 106 + * 107 + * @data: Number or number range or number group. 108 + * @ptr: Pointer to "struct tomoyo_number_union". 109 + * 110 + * Returns true on success, false otherwise. 111 + */ 112 + bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num) 113 + { 114 + u8 type; 115 + unsigned long v; 116 + memset(num, 0, sizeof(*num)); 117 + if (data[0] == '@') { 118 + if (!tomoyo_correct_word(data)) 119 + return false; 120 + num->group = tomoyo_get_group(data + 1, TOMOYO_NUMBER_GROUP); 121 + num->is_group = true; 122 + return num->group != NULL; 123 + } 124 + type = tomoyo_parse_ulong(&v, &data); 125 + if (!type) 126 + return false; 127 + num->values[0] = v; 128 + num->min_type = type; 129 + if (!*data) { 130 + num->values[1] = v; 131 + num->max_type = type; 132 + return true; 133 + } 134 + if (*data++ != '-') 135 + return false; 136 + type = tomoyo_parse_ulong(&v, &data); 137 + if (!type || *data) 138 + return false; 139 + num->values[1] = v; 140 + num->max_type = type; 141 + return true; 142 + } 143 + 144 + /** 145 + * tomoyo_byte_range - Check whether the string is a \ooo style octal value. 146 + * 147 + * @str: Pointer to the string. 148 + * 149 + * Returns true if @str is a \ooo style octal value, false otherwise. 150 + * 151 + * TOMOYO uses \ooo style representation for 0x01 - 0x20 and 0x7F - 0xFF. 152 + * This function verifies that \ooo is in valid range. 153 + */ 154 + static inline bool tomoyo_byte_range(const char *str) 155 + { 156 + return *str >= '0' && *str++ <= '3' && 157 + *str >= '0' && *str++ <= '7' && 158 + *str >= '0' && *str <= '7'; 159 + } 160 + 161 + /** 162 + * tomoyo_alphabet_char - Check whether the character is an alphabet. 163 + * 164 + * @c: The character to check. 165 + * 166 + * Returns true if @c is an alphabet character, false otherwise. 167 + */ 168 + static inline bool tomoyo_alphabet_char(const char c) 169 + { 170 + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); 171 + } 172 + 173 + /** 174 + * tomoyo_make_byte - Make byte value from three octal characters. 175 + * 176 + * @c1: The first character. 177 + * @c2: The second character. 178 + * @c3: The third character. 179 + * 180 + * Returns byte value. 181 + */ 182 + static inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3) 183 + { 184 + return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0'); 185 + } 186 + 187 + /** 188 + * tomoyo_str_starts - Check whether the given string starts with the given keyword. 189 + * 190 + * @src: Pointer to pointer to the string. 191 + * @find: Pointer to the keyword. 192 + * 193 + * Returns true if @src starts with @find, false otherwise. 194 + * 195 + * The @src is updated to point the first character after the @find 196 + * if @src starts with @find. 197 + */ 198 + bool tomoyo_str_starts(char **src, const char *find) 199 + { 200 + const int len = strlen(find); 201 + char *tmp = *src; 202 + 203 + if (strncmp(tmp, find, len)) 204 + return false; 205 + tmp += len; 206 + *src = tmp; 207 + return true; 208 + } 209 + 210 + /** 211 + * tomoyo_normalize_line - Format string. 212 + * 213 + * @buffer: The line to normalize. 214 + * 215 + * Leading and trailing whitespaces are removed. 216 + * Multiple whitespaces are packed into single space. 217 + * 218 + * Returns nothing. 219 + */ 220 + void tomoyo_normalize_line(unsigned char *buffer) 221 + { 222 + unsigned char *sp = buffer; 223 + unsigned char *dp = buffer; 224 + bool first = true; 225 + 226 + while (tomoyo_invalid(*sp)) 227 + sp++; 228 + while (*sp) { 229 + if (!first) 230 + *dp++ = ' '; 231 + first = false; 232 + while (tomoyo_valid(*sp)) 233 + *dp++ = *sp++; 234 + while (tomoyo_invalid(*sp)) 235 + sp++; 236 + } 237 + *dp = '\0'; 238 + } 239 + 240 + /** 241 + * tomoyo_tokenize - Tokenize string. 242 + * 243 + * @buffer: The line to tokenize. 244 + * @w: Pointer to "char *". 245 + * @size: Sizeof @w . 246 + * 247 + * Returns true on success, false otherwise. 248 + */ 249 + bool tomoyo_tokenize(char *buffer, char *w[], size_t size) 250 + { 251 + int count = size / sizeof(char *); 252 + int i; 253 + for (i = 0; i < count; i++) 254 + w[i] = ""; 255 + for (i = 0; i < count; i++) { 256 + char *cp = strchr(buffer, ' '); 257 + if (cp) 258 + *cp = '\0'; 259 + w[i] = buffer; 260 + if (!cp) 261 + break; 262 + buffer = cp + 1; 263 + } 264 + return i < count || !*buffer; 265 + } 266 + 267 + /** 268 + * tomoyo_correct_word2 - Validate a string. 269 + * 270 + * @string: The string to check. May be non-'\0'-terminated. 271 + * @len: Length of @string. 272 + * 273 + * Check whether the given string follows the naming rules. 274 + * Returns true if @string follows the naming rules, false otherwise. 275 + */ 276 + static bool tomoyo_correct_word2(const char *string, size_t len) 277 + { 278 + const char *const start = string; 279 + bool in_repetition = false; 280 + unsigned char c; 281 + unsigned char d; 282 + unsigned char e; 283 + if (!len) 284 + goto out; 285 + while (len--) { 286 + c = *string++; 287 + if (c == '\\') { 288 + if (!len--) 289 + goto out; 290 + c = *string++; 291 + switch (c) { 292 + case '\\': /* "\\" */ 293 + continue; 294 + case '$': /* "\$" */ 295 + case '+': /* "\+" */ 296 + case '?': /* "\?" */ 297 + case '*': /* "\*" */ 298 + case '@': /* "\@" */ 299 + case 'x': /* "\x" */ 300 + case 'X': /* "\X" */ 301 + case 'a': /* "\a" */ 302 + case 'A': /* "\A" */ 303 + case '-': /* "\-" */ 304 + continue; 305 + case '{': /* "/\{" */ 306 + if (string - 3 < start || *(string - 3) != '/') 307 + break; 308 + in_repetition = true; 309 + continue; 310 + case '}': /* "\}/" */ 311 + if (*string != '/') 312 + break; 313 + if (!in_repetition) 314 + break; 315 + in_repetition = false; 316 + continue; 317 + case '0': /* "\ooo" */ 318 + case '1': 319 + case '2': 320 + case '3': 321 + if (!len-- || !len--) 322 + break; 323 + d = *string++; 324 + e = *string++; 325 + if (d < '0' || d > '7' || e < '0' || e > '7') 326 + break; 327 + c = tomoyo_make_byte(c, d, e); 328 + if (tomoyo_invalid(c)) 329 + continue; /* pattern is not \000 */ 330 + } 331 + goto out; 332 + } else if (in_repetition && c == '/') { 333 + goto out; 334 + } else if (tomoyo_invalid(c)) { 335 + goto out; 336 + } 337 + } 338 + if (in_repetition) 339 + goto out; 340 + return true; 341 + out: 342 + return false; 343 + } 344 + 345 + /** 346 + * tomoyo_correct_word - Validate a string. 347 + * 348 + * @string: The string to check. 349 + * 350 + * Check whether the given string follows the naming rules. 351 + * Returns true if @string follows the naming rules, false otherwise. 352 + */ 353 + bool tomoyo_correct_word(const char *string) 354 + { 355 + return tomoyo_correct_word2(string, strlen(string)); 356 + } 357 + 358 + /** 359 + * tomoyo_correct_path - Validate a pathname. 360 + * 361 + * @filename: The pathname to check. 362 + * 363 + * Check whether the given pathname follows the naming rules. 364 + * Returns true if @filename follows the naming rules, false otherwise. 365 + */ 366 + bool tomoyo_correct_path(const char *filename) 367 + { 368 + return *filename == '/' && tomoyo_correct_word(filename); 369 + } 370 + 371 + /** 372 + * tomoyo_correct_domain - Check whether the given domainname follows the naming rules. 373 + * 374 + * @domainname: The domainname to check. 375 + * 376 + * Returns true if @domainname follows the naming rules, false otherwise. 377 + */ 378 + bool tomoyo_correct_domain(const unsigned char *domainname) 379 + { 380 + if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME, 381 + TOMOYO_ROOT_NAME_LEN)) 382 + goto out; 383 + domainname += TOMOYO_ROOT_NAME_LEN; 384 + if (!*domainname) 385 + return true; 386 + if (*domainname++ != ' ') 387 + goto out; 388 + while (1) { 389 + const unsigned char *cp = strchr(domainname, ' '); 390 + if (!cp) 391 + break; 392 + if (*domainname != '/' || 393 + !tomoyo_correct_word2(domainname, cp - domainname - 1)) 394 + goto out; 395 + domainname = cp + 1; 396 + } 397 + return tomoyo_correct_path(domainname); 398 + out: 399 + return false; 400 + } 401 + 402 + /** 403 + * tomoyo_domain_def - Check whether the given token can be a domainname. 404 + * 405 + * @buffer: The token to check. 406 + * 407 + * Returns true if @buffer possibly be a domainname, false otherwise. 408 + */ 409 + bool tomoyo_domain_def(const unsigned char *buffer) 410 + { 411 + return !strncmp(buffer, TOMOYO_ROOT_NAME, TOMOYO_ROOT_NAME_LEN); 412 + } 413 + 414 + /** 415 + * tomoyo_find_domain - Find a domain by the given name. 416 + * 417 + * @domainname: The domainname to find. 418 + * 419 + * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise. 420 + * 421 + * Caller holds tomoyo_read_lock(). 422 + */ 423 + struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname) 424 + { 425 + struct tomoyo_domain_info *domain; 426 + struct tomoyo_path_info name; 427 + 428 + name.name = domainname; 429 + tomoyo_fill_path_info(&name); 430 + list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { 431 + if (!domain->is_deleted && 432 + !tomoyo_pathcmp(&name, domain->domainname)) 433 + return domain; 434 + } 435 + return NULL; 436 + } 437 + 438 + /** 439 + * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token. 440 + * 441 + * @filename: The string to evaluate. 442 + * 443 + * Returns the initial length without a pattern in @filename. 444 + */ 445 + static int tomoyo_const_part_length(const char *filename) 446 + { 447 + char c; 448 + int len = 0; 449 + 450 + if (!filename) 451 + return 0; 452 + while ((c = *filename++) != '\0') { 453 + if (c != '\\') { 454 + len++; 455 + continue; 456 + } 457 + c = *filename++; 458 + switch (c) { 459 + case '\\': /* "\\" */ 460 + len += 2; 461 + continue; 462 + case '0': /* "\ooo" */ 463 + case '1': 464 + case '2': 465 + case '3': 466 + c = *filename++; 467 + if (c < '0' || c > '7') 468 + break; 469 + c = *filename++; 470 + if (c < '0' || c > '7') 471 + break; 472 + len += 4; 473 + continue; 474 + } 475 + break; 476 + } 477 + return len; 478 + } 479 + 480 + /** 481 + * tomoyo_fill_path_info - Fill in "struct tomoyo_path_info" members. 482 + * 483 + * @ptr: Pointer to "struct tomoyo_path_info" to fill in. 484 + * 485 + * The caller sets "struct tomoyo_path_info"->name. 486 + */ 487 + void tomoyo_fill_path_info(struct tomoyo_path_info *ptr) 488 + { 489 + const char *name = ptr->name; 490 + const int len = strlen(name); 491 + 492 + ptr->const_len = tomoyo_const_part_length(name); 493 + ptr->is_dir = len && (name[len - 1] == '/'); 494 + ptr->is_patterned = (ptr->const_len < len); 495 + ptr->hash = full_name_hash(name, len); 496 + } 497 + 498 + /** 499 + * tomoyo_file_matches_pattern2 - Pattern matching without '/' character and "\-" pattern. 500 + * 501 + * @filename: The start of string to check. 502 + * @filename_end: The end of string to check. 503 + * @pattern: The start of pattern to compare. 504 + * @pattern_end: The end of pattern to compare. 505 + * 506 + * Returns true if @filename matches @pattern, false otherwise. 507 + */ 508 + static bool tomoyo_file_matches_pattern2(const char *filename, 509 + const char *filename_end, 510 + const char *pattern, 511 + const char *pattern_end) 512 + { 513 + while (filename < filename_end && pattern < pattern_end) { 514 + char c; 515 + if (*pattern != '\\') { 516 + if (*filename++ != *pattern++) 517 + return false; 518 + continue; 519 + } 520 + c = *filename; 521 + pattern++; 522 + switch (*pattern) { 523 + int i; 524 + int j; 525 + case '?': 526 + if (c == '/') { 527 + return false; 528 + } else if (c == '\\') { 529 + if (filename[1] == '\\') 530 + filename++; 531 + else if (tomoyo_byte_range(filename + 1)) 532 + filename += 3; 533 + else 534 + return false; 535 + } 536 + break; 537 + case '\\': 538 + if (c != '\\') 539 + return false; 540 + if (*++filename != '\\') 541 + return false; 542 + break; 543 + case '+': 544 + if (!isdigit(c)) 545 + return false; 546 + break; 547 + case 'x': 548 + if (!isxdigit(c)) 549 + return false; 550 + break; 551 + case 'a': 552 + if (!tomoyo_alphabet_char(c)) 553 + return false; 554 + break; 555 + case '0': 556 + case '1': 557 + case '2': 558 + case '3': 559 + if (c == '\\' && tomoyo_byte_range(filename + 1) 560 + && strncmp(filename + 1, pattern, 3) == 0) { 561 + filename += 3; 562 + pattern += 2; 563 + break; 564 + } 565 + return false; /* Not matched. */ 566 + case '*': 567 + case '@': 568 + for (i = 0; i <= filename_end - filename; i++) { 569 + if (tomoyo_file_matches_pattern2( 570 + filename + i, filename_end, 571 + pattern + 1, pattern_end)) 572 + return true; 573 + c = filename[i]; 574 + if (c == '.' && *pattern == '@') 575 + break; 576 + if (c != '\\') 577 + continue; 578 + if (filename[i + 1] == '\\') 579 + i++; 580 + else if (tomoyo_byte_range(filename + i + 1)) 581 + i += 3; 582 + else 583 + break; /* Bad pattern. */ 584 + } 585 + return false; /* Not matched. */ 586 + default: 587 + j = 0; 588 + c = *pattern; 589 + if (c == '$') { 590 + while (isdigit(filename[j])) 591 + j++; 592 + } else if (c == 'X') { 593 + while (isxdigit(filename[j])) 594 + j++; 595 + } else if (c == 'A') { 596 + while (tomoyo_alphabet_char(filename[j])) 597 + j++; 598 + } 599 + for (i = 1; i <= j; i++) { 600 + if (tomoyo_file_matches_pattern2( 601 + filename + i, filename_end, 602 + pattern + 1, pattern_end)) 603 + return true; 604 + } 605 + return false; /* Not matched or bad pattern. */ 606 + } 607 + filename++; 608 + pattern++; 609 + } 610 + while (*pattern == '\\' && 611 + (*(pattern + 1) == '*' || *(pattern + 1) == '@')) 612 + pattern += 2; 613 + return filename == filename_end && pattern == pattern_end; 614 + } 615 + 616 + /** 617 + * tomoyo_file_matches_pattern - Pattern matching without '/' character. 618 + * 619 + * @filename: The start of string to check. 620 + * @filename_end: The end of string to check. 621 + * @pattern: The start of pattern to compare. 622 + * @pattern_end: The end of pattern to compare. 623 + * 624 + * Returns true if @filename matches @pattern, false otherwise. 625 + */ 626 + static bool tomoyo_file_matches_pattern(const char *filename, 627 + const char *filename_end, 628 + const char *pattern, 629 + const char *pattern_end) 630 + { 631 + const char *pattern_start = pattern; 632 + bool first = true; 633 + bool result; 634 + 635 + while (pattern < pattern_end - 1) { 636 + /* Split at "\-" pattern. */ 637 + if (*pattern++ != '\\' || *pattern++ != '-') 638 + continue; 639 + result = tomoyo_file_matches_pattern2(filename, 640 + filename_end, 641 + pattern_start, 642 + pattern - 2); 643 + if (first) 644 + result = !result; 645 + if (result) 646 + return false; 647 + first = false; 648 + pattern_start = pattern; 649 + } 650 + result = tomoyo_file_matches_pattern2(filename, filename_end, 651 + pattern_start, pattern_end); 652 + return first ? result : !result; 653 + } 654 + 655 + /** 656 + * tomoyo_path_matches_pattern2 - Do pathname pattern matching. 657 + * 658 + * @f: The start of string to check. 659 + * @p: The start of pattern to compare. 660 + * 661 + * Returns true if @f matches @p, false otherwise. 662 + */ 663 + static bool tomoyo_path_matches_pattern2(const char *f, const char *p) 664 + { 665 + const char *f_delimiter; 666 + const char *p_delimiter; 667 + 668 + while (*f && *p) { 669 + f_delimiter = strchr(f, '/'); 670 + if (!f_delimiter) 671 + f_delimiter = f + strlen(f); 672 + p_delimiter = strchr(p, '/'); 673 + if (!p_delimiter) 674 + p_delimiter = p + strlen(p); 675 + if (*p == '\\' && *(p + 1) == '{') 676 + goto recursive; 677 + if (!tomoyo_file_matches_pattern(f, f_delimiter, p, 678 + p_delimiter)) 679 + return false; 680 + f = f_delimiter; 681 + if (*f) 682 + f++; 683 + p = p_delimiter; 684 + if (*p) 685 + p++; 686 + } 687 + /* Ignore trailing "\*" and "\@" in @pattern. */ 688 + while (*p == '\\' && 689 + (*(p + 1) == '*' || *(p + 1) == '@')) 690 + p += 2; 691 + return !*f && !*p; 692 + recursive: 693 + /* 694 + * The "\{" pattern is permitted only after '/' character. 695 + * This guarantees that below "*(p - 1)" is safe. 696 + * Also, the "\}" pattern is permitted only before '/' character 697 + * so that "\{" + "\}" pair will not break the "\-" operator. 698 + */ 699 + if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' || 700 + *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\') 701 + return false; /* Bad pattern. */ 702 + do { 703 + /* Compare current component with pattern. */ 704 + if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2, 705 + p_delimiter - 2)) 706 + break; 707 + /* Proceed to next component. */ 708 + f = f_delimiter; 709 + if (!*f) 710 + break; 711 + f++; 712 + /* Continue comparison. */ 713 + if (tomoyo_path_matches_pattern2(f, p_delimiter + 1)) 714 + return true; 715 + f_delimiter = strchr(f, '/'); 716 + } while (f_delimiter); 717 + return false; /* Not matched. */ 718 + } 719 + 720 + /** 721 + * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern. 722 + * 723 + * @filename: The filename to check. 724 + * @pattern: The pattern to compare. 725 + * 726 + * Returns true if matches, false otherwise. 727 + * 728 + * The following patterns are available. 729 + * \\ \ itself. 730 + * \ooo Octal representation of a byte. 731 + * \* Zero or more repetitions of characters other than '/'. 732 + * \@ Zero or more repetitions of characters other than '/' or '.'. 733 + * \? 1 byte character other than '/'. 734 + * \$ One or more repetitions of decimal digits. 735 + * \+ 1 decimal digit. 736 + * \X One or more repetitions of hexadecimal digits. 737 + * \x 1 hexadecimal digit. 738 + * \A One or more repetitions of alphabet characters. 739 + * \a 1 alphabet character. 740 + * 741 + * \- Subtraction operator. 742 + * 743 + * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/ 744 + * /dir/dir/dir/ ). 745 + */ 746 + bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, 747 + const struct tomoyo_path_info *pattern) 748 + { 749 + const char *f = filename->name; 750 + const char *p = pattern->name; 751 + const int len = pattern->const_len; 752 + 753 + /* If @pattern doesn't contain pattern, I can use strcmp(). */ 754 + if (!pattern->is_patterned) 755 + return !tomoyo_pathcmp(filename, pattern); 756 + /* Don't compare directory and non-directory. */ 757 + if (filename->is_dir != pattern->is_dir) 758 + return false; 759 + /* Compare the initial length without patterns. */ 760 + if (strncmp(f, p, len)) 761 + return false; 762 + f += len; 763 + p += len; 764 + return tomoyo_path_matches_pattern2(f, p); 765 + } 766 + 767 + /** 768 + * tomoyo_get_exe - Get tomoyo_realpath() of current process. 769 + * 770 + * Returns the tomoyo_realpath() of current process on success, NULL otherwise. 771 + * 772 + * This function uses kzalloc(), so the caller must call kfree() 773 + * if this function didn't return NULL. 774 + */ 775 + const char *tomoyo_get_exe(void) 776 + { 777 + struct mm_struct *mm = current->mm; 778 + struct vm_area_struct *vma; 779 + const char *cp = NULL; 780 + 781 + if (!mm) 782 + return NULL; 783 + down_read(&mm->mmap_sem); 784 + for (vma = mm->mmap; vma; vma = vma->vm_next) { 785 + if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) { 786 + cp = tomoyo_realpath_from_path(&vma->vm_file->f_path); 787 + break; 788 + } 789 + } 790 + up_read(&mm->mmap_sem); 791 + return cp; 792 + } 793 + 794 + /** 795 + * tomoyo_get_mode - Get MAC mode. 796 + * 797 + * @profile: Profile number. 798 + * @index: Index number of functionality. 799 + * 800 + * Returns mode. 801 + */ 802 + int tomoyo_get_mode(const u8 profile, const u8 index) 803 + { 804 + u8 mode; 805 + const u8 category = TOMOYO_MAC_CATEGORY_FILE; 806 + if (!tomoyo_policy_loaded) 807 + return TOMOYO_CONFIG_DISABLED; 808 + mode = tomoyo_profile(profile)->config[index]; 809 + if (mode == TOMOYO_CONFIG_USE_DEFAULT) 810 + mode = tomoyo_profile(profile)->config[category]; 811 + if (mode == TOMOYO_CONFIG_USE_DEFAULT) 812 + mode = tomoyo_profile(profile)->default_config; 813 + return mode & 3; 814 + } 815 + 816 + /** 817 + * tomoyo_init_request_info - Initialize "struct tomoyo_request_info" members. 818 + * 819 + * @r: Pointer to "struct tomoyo_request_info" to initialize. 820 + * @domain: Pointer to "struct tomoyo_domain_info". NULL for tomoyo_domain(). 821 + * @index: Index number of functionality. 822 + * 823 + * Returns mode. 824 + */ 825 + int tomoyo_init_request_info(struct tomoyo_request_info *r, 826 + struct tomoyo_domain_info *domain, const u8 index) 827 + { 828 + u8 profile; 829 + memset(r, 0, sizeof(*r)); 830 + if (!domain) 831 + domain = tomoyo_domain(); 832 + r->domain = domain; 833 + profile = domain->profile; 834 + r->profile = profile; 835 + r->type = index; 836 + r->mode = tomoyo_get_mode(profile, index); 837 + return r->mode; 838 + } 839 + 840 + /** 841 + * tomoyo_last_word - Get last component of a line. 842 + * 843 + * @line: A line. 844 + * 845 + * Returns the last word of a line. 846 + */ 847 + const char *tomoyo_last_word(const char *name) 848 + { 849 + const char *cp = strrchr(name, ' '); 850 + if (cp) 851 + return cp + 1; 852 + return name; 853 + } 854 + 855 + /** 856 + * tomoyo_warn_log - Print warning or error message on console. 857 + * 858 + * @r: Pointer to "struct tomoyo_request_info". 859 + * @fmt: The printf()'s format string, followed by parameters. 860 + */ 861 + void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...) 862 + { 863 + va_list args; 864 + char *buffer; 865 + const struct tomoyo_domain_info * const domain = r->domain; 866 + const struct tomoyo_profile *profile = tomoyo_profile(domain->profile); 867 + switch (r->mode) { 868 + case TOMOYO_CONFIG_ENFORCING: 869 + if (!profile->enforcing->enforcing_verbose) 870 + return; 871 + break; 872 + case TOMOYO_CONFIG_PERMISSIVE: 873 + if (!profile->permissive->permissive_verbose) 874 + return; 875 + break; 876 + case TOMOYO_CONFIG_LEARNING: 877 + if (!profile->learning->learning_verbose) 878 + return; 879 + break; 880 + } 881 + buffer = kmalloc(4096, GFP_NOFS); 882 + if (!buffer) 883 + return; 884 + va_start(args, fmt); 885 + vsnprintf(buffer, 4095, fmt, args); 886 + va_end(args); 887 + buffer[4095] = '\0'; 888 + printk(KERN_WARNING "%s: Access %s denied for %s\n", 889 + r->mode == TOMOYO_CONFIG_ENFORCING ? "ERROR" : "WARNING", buffer, 890 + tomoyo_last_word(domain->domainname->name)); 891 + kfree(buffer); 892 + } 893 + 894 + /** 895 + * tomoyo_domain_quota_is_ok - Check for domain's quota. 896 + * 897 + * @r: Pointer to "struct tomoyo_request_info". 898 + * 899 + * Returns true if the domain is not exceeded quota, false otherwise. 900 + * 901 + * Caller holds tomoyo_read_lock(). 902 + */ 903 + bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) 904 + { 905 + unsigned int count = 0; 906 + struct tomoyo_domain_info *domain = r->domain; 907 + struct tomoyo_acl_info *ptr; 908 + 909 + if (r->mode != TOMOYO_CONFIG_LEARNING) 910 + return false; 911 + if (!domain) 912 + return true; 913 + list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 914 + if (ptr->is_deleted) 915 + continue; 916 + switch (ptr->type) { 917 + u16 perm; 918 + u8 i; 919 + case TOMOYO_TYPE_PATH_ACL: 920 + perm = container_of(ptr, struct tomoyo_path_acl, head) 921 + ->perm; 922 + for (i = 0; i < TOMOYO_MAX_PATH_OPERATION; i++) 923 + if (perm & (1 << i)) 924 + count++; 925 + if (perm & (1 << TOMOYO_TYPE_READ_WRITE)) 926 + count -= 2; 927 + break; 928 + case TOMOYO_TYPE_PATH2_ACL: 929 + perm = container_of(ptr, struct tomoyo_path2_acl, head) 930 + ->perm; 931 + for (i = 0; i < TOMOYO_MAX_PATH2_OPERATION; i++) 932 + if (perm & (1 << i)) 933 + count++; 934 + break; 935 + case TOMOYO_TYPE_PATH_NUMBER_ACL: 936 + perm = container_of(ptr, struct tomoyo_path_number_acl, 937 + head)->perm; 938 + for (i = 0; i < TOMOYO_MAX_PATH_NUMBER_OPERATION; i++) 939 + if (perm & (1 << i)) 940 + count++; 941 + break; 942 + case TOMOYO_TYPE_MKDEV_ACL: 943 + perm = container_of(ptr, struct tomoyo_mkdev_acl, 944 + head)->perm; 945 + for (i = 0; i < TOMOYO_MAX_MKDEV_OPERATION; i++) 946 + if (perm & (1 << i)) 947 + count++; 948 + break; 949 + default: 950 + count++; 951 + } 952 + } 953 + if (count < tomoyo_profile(domain->profile)->learning-> 954 + learning_max_entry) 955 + return true; 956 + if (!domain->quota_warned) { 957 + domain->quota_warned = true; 958 + printk(KERN_WARNING "TOMOYO-WARNING: " 959 + "Domain '%s' has so many ACLs to hold. " 960 + "Stopped learning mode.\n", domain->domainname->name); 961 + } 962 + return false; 963 + }