tomoyo.c revision 35d50e60e8b12e4adc2fa317343a176d87294a72
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-pre 2009/02/01 9 * 10 */ 11 12#include <linux/security.h> 13#include "common.h" 14#include "tomoyo.h" 15#include "realpath.h" 16 17static 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 28static 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 50static 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 75static 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 */ 97static 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 133static 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 150static 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 158static 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 166static 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 175static 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 183static 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 192static 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 216static 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 226static 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 238static 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 246static 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 259static 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 279static 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 return 0; 291} 292 293security_initcall(tomoyo_init); 294