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_prepare(struct cred *new, const struct cred *old, 18 gfp_t gfp) 19 { 20 /* 21 * Since "struct tomoyo_domain_info *" is a sharable pointer, 22 * we don't need to duplicate. 23 */ 24 new->security = old->security; 25 return 0; 26 } 27 28 static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) 29 { 30 /* 31 * Do only if this function is called for the first time of an execve 32 * operation. 33 */ 34 if (bprm->cred_prepared) 35 return 0; 36 /* 37 * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested 38 * for the first time. 39 */ 40 if (!tomoyo_policy_loaded) 41 tomoyo_load_policy(bprm->filename); 42 /* 43 * Tell tomoyo_bprm_check_security() is called for the first time of an 44 * execve operation. 45 */ 46 bprm->cred->security = NULL; 47 return 0; 48 } 49 50 static int tomoyo_bprm_check_security(struct linux_binprm *bprm) 51 { 52 struct tomoyo_domain_info *domain = bprm->cred->security; 53 54 /* 55 * Execute permission is checked against pathname passed to do_execve() 56 * using current domain. 57 */ 58 if (!domain) { 59 struct tomoyo_domain_info *next_domain = NULL; 60 int retval = tomoyo_find_next_domain(bprm, &next_domain); 61 62 if (!retval) 63 bprm->cred->security = next_domain; 64 return retval; 65 } 66 /* 67 * Read permission is checked against interpreters using next domain. 68 * '1' is the result of open_to_namei_flags(O_RDONLY). 69 */ 70 return tomoyo_check_open_permission(domain, &bprm->file->f_path, 1); 71 } 72 73 #ifdef CONFIG_SYSCTL 74 75 static int tomoyo_prepend(char **buffer, int *buflen, const char *str) 76 { 77 int namelen = strlen(str); 78 79 if (*buflen < namelen) 80 return -ENOMEM; 81 *buflen -= namelen; 82 *buffer -= namelen; 83 memcpy(*buffer, str, namelen); 84 return 0; 85 } 86 87 /** 88 * tomoyo_sysctl_path - return the realpath of a ctl_table. 89 * @table: pointer to "struct ctl_table". 90 * 91 * Returns realpath(3) of the @table on success. 92 * Returns NULL on failure. 93 * 94 * This function uses tomoyo_alloc(), so the caller must call tomoyo_free() 95 * if this function didn't return NULL. 96 */ 97 static char *tomoyo_sysctl_path(struct ctl_table *table) 98 { 99 int buflen = TOMOYO_MAX_PATHNAME_LEN; 100 char *buf = tomoyo_alloc(buflen); 101 char *end = buf + buflen; 102 int error = -ENOMEM; 103 104 if (!buf) 105 return NULL; 106 107 *--end = '\0'; 108 buflen--; 109 while (table) { 110 char num[32]; 111 const char *sp = table->procname; 112 113 if (!sp) { 114 memset(num, 0, sizeof(num)); 115 snprintf(num, sizeof(num) - 1, "=%d=", table->ctl_name); 116 sp = num; 117 } 118 if (tomoyo_prepend(&end, &buflen, sp) || 119 tomoyo_prepend(&end, &buflen, "/")) 120 goto out; 121 table = table->parent; 122 } 123 if (tomoyo_prepend(&end, &buflen, "/proc/sys")) 124 goto out; 125 error = tomoyo_encode(buf, end - buf, end); 126 out: 127 if (!error) 128 return buf; 129 tomoyo_free(buf); 130 return NULL; 131 } 132 133 static int tomoyo_sysctl(struct ctl_table *table, int op) 134 { 135 int error; 136 char *name; 137 138 op &= MAY_READ | MAY_WRITE; 139 if (!op) 140 return 0; 141 name = tomoyo_sysctl_path(table); 142 if (!name) 143 return -ENOMEM; 144 error = tomoyo_check_file_perm(tomoyo_domain(), name, op); 145 tomoyo_free(name); 146 return error; 147 } 148 #endif 149 150 static int tomoyo_path_truncate(struct path *path, loff_t length, 151 unsigned int time_attrs) 152 { 153 return tomoyo_check_1path_perm(tomoyo_domain(), 154 TOMOYO_TYPE_TRUNCATE_ACL, 155 path); 156 } 157 158 static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry) 159 { 160 struct path path = { parent->mnt, dentry }; 161 return tomoyo_check_1path_perm(tomoyo_domain(), 162 TOMOYO_TYPE_UNLINK_ACL, 163 &path); 164 } 165 166 static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, 167 int mode) 168 { 169 struct path path = { parent->mnt, dentry }; 170 return tomoyo_check_1path_perm(tomoyo_domain(), 171 TOMOYO_TYPE_MKDIR_ACL, 172 &path); 173 } 174 175 static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) 176 { 177 struct path path = { parent->mnt, dentry }; 178 return tomoyo_check_1path_perm(tomoyo_domain(), 179 TOMOYO_TYPE_RMDIR_ACL, 180 &path); 181 } 182 183 static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry, 184 const char *old_name) 185 { 186 struct path path = { parent->mnt, dentry }; 187 return tomoyo_check_1path_perm(tomoyo_domain(), 188 TOMOYO_TYPE_SYMLINK_ACL, 189 &path); 190 } 191 192 static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, 193 int mode, unsigned int dev) 194 { 195 struct path path = { parent->mnt, dentry }; 196 int type = TOMOYO_TYPE_CREATE_ACL; 197 198 switch (mode & S_IFMT) { 199 case S_IFCHR: 200 type = TOMOYO_TYPE_MKCHAR_ACL; 201 break; 202 case S_IFBLK: 203 type = TOMOYO_TYPE_MKBLOCK_ACL; 204 break; 205 case S_IFIFO: 206 type = TOMOYO_TYPE_MKFIFO_ACL; 207 break; 208 case S_IFSOCK: 209 type = TOMOYO_TYPE_MKSOCK_ACL; 210 break; 211 } 212 return tomoyo_check_1path_perm(tomoyo_domain(), 213 type, &path); 214 } 215 216 static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, 217 struct dentry *new_dentry) 218 { 219 struct path path1 = { new_dir->mnt, old_dentry }; 220 struct path path2 = { new_dir->mnt, new_dentry }; 221 return tomoyo_check_2path_perm(tomoyo_domain(), 222 TOMOYO_TYPE_LINK_ACL, 223 &path1, &path2); 224 } 225 226 static int tomoyo_path_rename(struct path *old_parent, 227 struct dentry *old_dentry, 228 struct path *new_parent, 229 struct dentry *new_dentry) 230 { 231 struct path path1 = { old_parent->mnt, old_dentry }; 232 struct path path2 = { new_parent->mnt, new_dentry }; 233 return tomoyo_check_2path_perm(tomoyo_domain(), 234 TOMOYO_TYPE_RENAME_ACL, 235 &path1, &path2); 236 } 237 238 static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, 239 unsigned long arg) 240 { 241 if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)) 242 return tomoyo_check_rewrite_permission(tomoyo_domain(), file); 243 return 0; 244 } 245 246 static int tomoyo_dentry_open(struct file *f, const struct cred *cred) 247 { 248 int flags = f->f_flags; 249 250 if ((flags + 1) & O_ACCMODE) 251 flags++; 252 flags |= f->f_flags & (O_APPEND | O_TRUNC); 253 /* Don't check read permission here if called from do_execve(). */ 254 if (current->in_execve) 255 return 0; 256 return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags); 257 } 258 259 static struct security_operations tomoyo_security_ops = { 260 .name = "tomoyo", 261 .cred_prepare = tomoyo_cred_prepare, 262 .bprm_set_creds = tomoyo_bprm_set_creds, 263 .bprm_check_security = tomoyo_bprm_check_security, 264 #ifdef CONFIG_SYSCTL 265 .sysctl = tomoyo_sysctl, 266 #endif 267 .file_fcntl = tomoyo_file_fcntl, 268 .dentry_open = tomoyo_dentry_open, 269 .path_truncate = tomoyo_path_truncate, 270 .path_unlink = tomoyo_path_unlink, 271 .path_mkdir = tomoyo_path_mkdir, 272 .path_rmdir = tomoyo_path_rmdir, 273 .path_symlink = tomoyo_path_symlink, 274 .path_mknod = tomoyo_path_mknod, 275 .path_link = tomoyo_path_link, 276 .path_rename = tomoyo_path_rename, 277 }; 278 279 static int __init tomoyo_init(void) 280 { 281 struct cred *cred = (struct cred *) current_cred(); 282 283 if (!security_module_enable(&tomoyo_security_ops)) 284 return 0; 285 /* register ourselves with the security framework */ 286 if (register_security(&tomoyo_security_ops)) 287 panic("Failure registering TOMOYO Linux"); 288 printk(KERN_INFO "TOMOYO Linux initialized\n"); 289 cred->security = &tomoyo_kernel_domain; 290 tomoyo_realpath_init(); 291 return 0; 292 } 293 294 security_initcall(tomoyo_init); 295