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