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 #include "tomoyo.h" 15 #include "realpath.h" 16 17 static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) 18 { 19 new->security = NULL; 20 return 0; 21 } 22 23 static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, 24 gfp_t gfp) 25 { 26 /* 27 * Since "struct tomoyo_domain_info *" is a sharable pointer, 28 * we don't need to duplicate. 29 */ 30 new->security = old->security; 31 return 0; 32 } 33 34 static void tomoyo_cred_transfer(struct cred *new, const struct cred *old) 35 { 36 /* 37 * Since "struct tomoyo_domain_info *" is a sharable pointer, 38 * we don't need to duplicate. 39 */ 40 new->security = old->security; 41 } 42 43 static 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 * Tell tomoyo_bprm_check_security() is called for the first time of an 65 * execve operation. 66 */ 67 bprm->cred->security = NULL; 68 return 0; 69 } 70 71 static int tomoyo_bprm_check_security(struct linux_binprm *bprm) 72 { 73 struct tomoyo_domain_info *domain = bprm->cred->security; 74 75 /* 76 * Execute permission is checked against pathname passed to do_execve() 77 * using current domain. 78 */ 79 if (!domain) 80 return tomoyo_find_next_domain(bprm); 81 /* 82 * Read permission is checked against interpreters using next domain. 83 * '1' is the result of open_to_namei_flags(O_RDONLY). 84 */ 85 return tomoyo_check_open_permission(domain, &bprm->file->f_path, 1); 86 } 87 88 static int tomoyo_path_truncate(struct path *path, loff_t length, 89 unsigned int time_attrs) 90 { 91 return tomoyo_check_1path_perm(tomoyo_domain(), 92 TOMOYO_TYPE_TRUNCATE_ACL, 93 path); 94 } 95 96 static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry) 97 { 98 struct path path = { parent->mnt, dentry }; 99 return tomoyo_check_1path_perm(tomoyo_domain(), 100 TOMOYO_TYPE_UNLINK_ACL, 101 &path); 102 } 103 104 static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, 105 int mode) 106 { 107 struct path path = { parent->mnt, dentry }; 108 return tomoyo_check_1path_perm(tomoyo_domain(), 109 TOMOYO_TYPE_MKDIR_ACL, 110 &path); 111 } 112 113 static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) 114 { 115 struct path path = { parent->mnt, dentry }; 116 return tomoyo_check_1path_perm(tomoyo_domain(), 117 TOMOYO_TYPE_RMDIR_ACL, 118 &path); 119 } 120 121 static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry, 122 const char *old_name) 123 { 124 struct path path = { parent->mnt, dentry }; 125 return tomoyo_check_1path_perm(tomoyo_domain(), 126 TOMOYO_TYPE_SYMLINK_ACL, 127 &path); 128 } 129 130 static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, 131 int mode, unsigned int dev) 132 { 133 struct path path = { parent->mnt, dentry }; 134 int type = TOMOYO_TYPE_CREATE_ACL; 135 136 switch (mode & S_IFMT) { 137 case S_IFCHR: 138 type = TOMOYO_TYPE_MKCHAR_ACL; 139 break; 140 case S_IFBLK: 141 type = TOMOYO_TYPE_MKBLOCK_ACL; 142 break; 143 case S_IFIFO: 144 type = TOMOYO_TYPE_MKFIFO_ACL; 145 break; 146 case S_IFSOCK: 147 type = TOMOYO_TYPE_MKSOCK_ACL; 148 break; 149 } 150 return tomoyo_check_1path_perm(tomoyo_domain(), 151 type, &path); 152 } 153 154 static 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_check_2path_perm(tomoyo_domain(), 160 TOMOYO_TYPE_LINK_ACL, 161 &path1, &path2); 162 } 163 164 static int tomoyo_path_rename(struct path *old_parent, 165 struct dentry *old_dentry, 166 struct path *new_parent, 167 struct dentry *new_dentry) 168 { 169 struct path path1 = { old_parent->mnt, old_dentry }; 170 struct path path2 = { new_parent->mnt, new_dentry }; 171 return tomoyo_check_2path_perm(tomoyo_domain(), 172 TOMOYO_TYPE_RENAME_ACL, 173 &path1, &path2); 174 } 175 176 static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, 177 unsigned long arg) 178 { 179 if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)) 180 return tomoyo_check_rewrite_permission(tomoyo_domain(), file); 181 return 0; 182 } 183 184 static int tomoyo_dentry_open(struct file *f, const struct cred *cred) 185 { 186 int flags = f->f_flags; 187 188 if ((flags + 1) & O_ACCMODE) 189 flags++; 190 flags |= f->f_flags & (O_APPEND | O_TRUNC); 191 /* Don't check read permission here if called from do_execve(). */ 192 if (current->in_execve) 193 return 0; 194 return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags); 195 } 196 197 /* 198 * tomoyo_security_ops is a "struct security_operations" which is used for 199 * registering TOMOYO. 200 */ 201 static struct security_operations tomoyo_security_ops = { 202 .name = "tomoyo", 203 .cred_alloc_blank = tomoyo_cred_alloc_blank, 204 .cred_prepare = tomoyo_cred_prepare, 205 .cred_transfer = tomoyo_cred_transfer, 206 .bprm_set_creds = tomoyo_bprm_set_creds, 207 .bprm_check_security = tomoyo_bprm_check_security, 208 .file_fcntl = tomoyo_file_fcntl, 209 .dentry_open = tomoyo_dentry_open, 210 .path_truncate = tomoyo_path_truncate, 211 .path_unlink = tomoyo_path_unlink, 212 .path_mkdir = tomoyo_path_mkdir, 213 .path_rmdir = tomoyo_path_rmdir, 214 .path_symlink = tomoyo_path_symlink, 215 .path_mknod = tomoyo_path_mknod, 216 .path_link = tomoyo_path_link, 217 .path_rename = tomoyo_path_rename, 218 }; 219 220 static int __init tomoyo_init(void) 221 { 222 struct cred *cred = (struct cred *) current_cred(); 223 224 if (!security_module_enable(&tomoyo_security_ops)) 225 return 0; 226 /* register ourselves with the security framework */ 227 if (register_security(&tomoyo_security_ops)) 228 panic("Failure registering TOMOYO Linux"); 229 printk(KERN_INFO "TOMOYO Linux initialized\n"); 230 cred->security = &tomoyo_kernel_domain; 231 tomoyo_realpath_init(); 232 return 0; 233 } 234 235 security_initcall(tomoyo_init); 236