tomoyo.c revision cb0abe6a5b58499bd4bc1403f4987af9ead0642c
1/* 2 * security/tomoyo/tomoyo.c 3 * 4 * LSM hooks for TOMOYO Linux. 5 * 6 * Copyright (C) 2005-2009 NTT DATA CORPORATION 7 * 8 * Version: 2.2.0 2009/04/01 9 * 10 */ 11 12#include <linux/security.h> 13#include "common.h" 14 15static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) 16{ 17 new->security = NULL; 18 return 0; 19} 20 21static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, 22 gfp_t gfp) 23{ 24 struct tomoyo_domain_info *domain = old->security; 25 new->security = domain; 26 if (domain) 27 atomic_inc(&domain->users); 28 return 0; 29} 30 31static void tomoyo_cred_transfer(struct cred *new, const struct cred *old) 32{ 33 tomoyo_cred_prepare(new, old, 0); 34} 35 36static void tomoyo_cred_free(struct cred *cred) 37{ 38 struct tomoyo_domain_info *domain = cred->security; 39 if (domain) 40 atomic_dec(&domain->users); 41} 42 43static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) 44{ 45 int rc; 46 47 rc = cap_bprm_set_creds(bprm); 48 if (rc) 49 return rc; 50 51 /* 52 * Do only if this function is called for the first time of an execve 53 * operation. 54 */ 55 if (bprm->cred_prepared) 56 return 0; 57 /* 58 * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested 59 * for the first time. 60 */ 61 if (!tomoyo_policy_loaded) 62 tomoyo_load_policy(bprm->filename); 63 /* 64 * Release reference to "struct tomoyo_domain_info" stored inside 65 * "bprm->cred->security". New reference to "struct tomoyo_domain_info" 66 * stored inside "bprm->cred->security" will be acquired later inside 67 * tomoyo_find_next_domain(). 68 */ 69 atomic_dec(&((struct tomoyo_domain_info *) 70 bprm->cred->security)->users); 71 /* 72 * Tell tomoyo_bprm_check_security() is called for the first time of an 73 * execve operation. 74 */ 75 bprm->cred->security = NULL; 76 return 0; 77} 78 79static int tomoyo_bprm_check_security(struct linux_binprm *bprm) 80{ 81 struct tomoyo_domain_info *domain = bprm->cred->security; 82 83 /* 84 * Execute permission is checked against pathname passed to do_execve() 85 * using current domain. 86 */ 87 if (!domain) { 88 const int idx = tomoyo_read_lock(); 89 const int err = tomoyo_find_next_domain(bprm); 90 tomoyo_read_unlock(idx); 91 return err; 92 } 93 /* 94 * Read permission is checked against interpreters using next domain. 95 */ 96 return tomoyo_check_open_permission(domain, &bprm->file->f_path, O_RDONLY); 97} 98 99static int tomoyo_path_truncate(struct path *path, loff_t length, 100 unsigned int time_attrs) 101{ 102 return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path); 103} 104 105static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry) 106{ 107 struct path path = { parent->mnt, dentry }; 108 return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path); 109} 110 111static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, 112 int mode) 113{ 114 struct path path = { parent->mnt, dentry }; 115 return tomoyo_path_perm(TOMOYO_TYPE_MKDIR, &path); 116} 117 118static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) 119{ 120 struct path path = { parent->mnt, dentry }; 121 return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path); 122} 123 124static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry, 125 const char *old_name) 126{ 127 struct path path = { parent->mnt, dentry }; 128 return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path); 129} 130 131static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, 132 int mode, unsigned int dev) 133{ 134 struct path path = { parent->mnt, dentry }; 135 int type = TOMOYO_TYPE_CREATE; 136 137 switch (mode & S_IFMT) { 138 case S_IFCHR: 139 type = TOMOYO_TYPE_MKCHAR; 140 break; 141 case S_IFBLK: 142 type = TOMOYO_TYPE_MKBLOCK; 143 break; 144 case S_IFIFO: 145 type = TOMOYO_TYPE_MKFIFO; 146 break; 147 case S_IFSOCK: 148 type = TOMOYO_TYPE_MKSOCK; 149 break; 150 } 151 return tomoyo_path_perm(type, &path); 152} 153 154static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, 155 struct dentry *new_dentry) 156{ 157 struct path path1 = { new_dir->mnt, old_dentry }; 158 struct path path2 = { new_dir->mnt, new_dentry }; 159 return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2); 160} 161 162static int tomoyo_path_rename(struct path *old_parent, 163 struct dentry *old_dentry, 164 struct path *new_parent, 165 struct dentry *new_dentry) 166{ 167 struct path path1 = { old_parent->mnt, old_dentry }; 168 struct path path2 = { new_parent->mnt, new_dentry }; 169 return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2); 170} 171 172static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, 173 unsigned long arg) 174{ 175 if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)) 176 return tomoyo_path_perm(TOMOYO_TYPE_REWRITE, &file->f_path); 177 return 0; 178} 179 180static int tomoyo_dentry_open(struct file *f, const struct cred *cred) 181{ 182 int flags = f->f_flags; 183 /* Don't check read permission here if called from do_execve(). */ 184 if (current->in_execve) 185 return 0; 186 return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags); 187} 188 189static int tomoyo_file_ioctl(struct file *file, unsigned int cmd, 190 unsigned long arg) 191{ 192 return tomoyo_path_perm(TOMOYO_TYPE_IOCTL, &file->f_path); 193} 194 195static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt, 196 mode_t mode) 197{ 198 struct path path = { mnt, dentry }; 199 return tomoyo_path_perm(TOMOYO_TYPE_CHMOD, &path); 200} 201 202static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid) 203{ 204 int error = 0; 205 if (uid != (uid_t) -1) 206 error = tomoyo_path_perm(TOMOYO_TYPE_CHOWN, path); 207 if (!error && gid != (gid_t) -1) 208 error = tomoyo_path_perm(TOMOYO_TYPE_CHGRP, path); 209 return error; 210} 211 212static int tomoyo_path_chroot(struct path *path) 213{ 214 return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path); 215} 216 217static int tomoyo_sb_mount(char *dev_name, struct path *path, 218 char *type, unsigned long flags, void *data) 219{ 220 return tomoyo_path_perm(TOMOYO_TYPE_MOUNT, path); 221} 222 223static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) 224{ 225 struct path path = { mnt, mnt->mnt_root }; 226 return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path); 227} 228 229static int tomoyo_sb_pivotroot(struct path *old_path, struct path *new_path) 230{ 231 return tomoyo_path2_perm(TOMOYO_TYPE_PIVOT_ROOT, new_path, old_path); 232} 233 234/* 235 * tomoyo_security_ops is a "struct security_operations" which is used for 236 * registering TOMOYO. 237 */ 238static struct security_operations tomoyo_security_ops = { 239 .name = "tomoyo", 240 .cred_alloc_blank = tomoyo_cred_alloc_blank, 241 .cred_prepare = tomoyo_cred_prepare, 242 .cred_transfer = tomoyo_cred_transfer, 243 .cred_free = tomoyo_cred_free, 244 .bprm_set_creds = tomoyo_bprm_set_creds, 245 .bprm_check_security = tomoyo_bprm_check_security, 246 .file_fcntl = tomoyo_file_fcntl, 247 .dentry_open = tomoyo_dentry_open, 248 .path_truncate = tomoyo_path_truncate, 249 .path_unlink = tomoyo_path_unlink, 250 .path_mkdir = tomoyo_path_mkdir, 251 .path_rmdir = tomoyo_path_rmdir, 252 .path_symlink = tomoyo_path_symlink, 253 .path_mknod = tomoyo_path_mknod, 254 .path_link = tomoyo_path_link, 255 .path_rename = tomoyo_path_rename, 256 .file_ioctl = tomoyo_file_ioctl, 257 .path_chmod = tomoyo_path_chmod, 258 .path_chown = tomoyo_path_chown, 259 .path_chroot = tomoyo_path_chroot, 260 .sb_mount = tomoyo_sb_mount, 261 .sb_umount = tomoyo_sb_umount, 262 .sb_pivotroot = tomoyo_sb_pivotroot, 263}; 264 265/* Lock for GC. */ 266struct srcu_struct tomoyo_ss; 267 268static int __init tomoyo_init(void) 269{ 270 struct cred *cred = (struct cred *) current_cred(); 271 272 if (!security_module_enable(&tomoyo_security_ops)) 273 return 0; 274 /* register ourselves with the security framework */ 275 if (register_security(&tomoyo_security_ops) || 276 init_srcu_struct(&tomoyo_ss)) 277 panic("Failure registering TOMOYO Linux"); 278 printk(KERN_INFO "TOMOYO Linux initialized\n"); 279 cred->security = &tomoyo_kernel_domain; 280 tomoyo_realpath_init(); 281 return 0; 282} 283 284security_initcall(tomoyo_init); 285