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 #ifdef CONFIG_SYSCTL 89 90 static int tomoyo_prepend(char **buffer, int *buflen, const char *str) 91 { 92 int namelen = strlen(str); 93 94 if (*buflen < namelen) 95 return -ENOMEM; 96 *buflen -= namelen; 97 *buffer -= namelen; 98 memcpy(*buffer, str, namelen); 99 return 0; 100 } 101 102 /** 103 * tomoyo_sysctl_path - return the realpath of a ctl_table. 104 * @table: pointer to "struct ctl_table". 105 * 106 * Returns realpath(3) of the @table on success. 107 * Returns NULL on failure. 108 * 109 * This function uses tomoyo_alloc(), so the caller must call tomoyo_free() 110 * if this function didn't return NULL. 111 */ 112 static char *tomoyo_sysctl_path(struct ctl_table *table) 113 { 114 int buflen = TOMOYO_MAX_PATHNAME_LEN; 115 char *buf = tomoyo_alloc(buflen); 116 char *end = buf + buflen; 117 int error = -ENOMEM; 118 119 if (!buf) 120 return NULL; 121 122 *--end = '\0'; 123 buflen--; 124 while (table) { 125 char num[32]; 126 const char *sp = table->procname; 127 128 if (!sp) { 129 memset(num, 0, sizeof(num)); 130 snprintf(num, sizeof(num) - 1, "=%d=", table->ctl_name); 131 sp = num; 132 } 133 if (tomoyo_prepend(&end, &buflen, sp) || 134 tomoyo_prepend(&end, &buflen, "/")) 135 goto out; 136 table = table->parent; 137 } 138 if (tomoyo_prepend(&end, &buflen, "/proc/sys")) 139 goto out; 140 error = tomoyo_encode(buf, end - buf, end); 141 out: 142 if (!error) 143 return buf; 144 tomoyo_free(buf); 145 return NULL; 146 } 147 148 static int tomoyo_sysctl(struct ctl_table *table, int op) 149 { 150 int error; 151 char *name; 152 153 op &= MAY_READ | MAY_WRITE; 154 if (!op) 155 return 0; 156 name = tomoyo_sysctl_path(table); 157 if (!name) 158 return -ENOMEM; 159 error = tomoyo_check_file_perm(tomoyo_domain(), name, op); 160 tomoyo_free(name); 161 return error; 162 } 163 #endif 164 165 static int tomoyo_path_truncate(struct path *path, loff_t length, 166 unsigned int time_attrs) 167 { 168 return tomoyo_check_1path_perm(tomoyo_domain(), 169 TOMOYO_TYPE_TRUNCATE_ACL, 170 path); 171 } 172 173 static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry) 174 { 175 struct path path = { parent->mnt, dentry }; 176 return tomoyo_check_1path_perm(tomoyo_domain(), 177 TOMOYO_TYPE_UNLINK_ACL, 178 &path); 179 } 180 181 static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, 182 int mode) 183 { 184 struct path path = { parent->mnt, dentry }; 185 return tomoyo_check_1path_perm(tomoyo_domain(), 186 TOMOYO_TYPE_MKDIR_ACL, 187 &path); 188 } 189 190 static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) 191 { 192 struct path path = { parent->mnt, dentry }; 193 return tomoyo_check_1path_perm(tomoyo_domain(), 194 TOMOYO_TYPE_RMDIR_ACL, 195 &path); 196 } 197 198 static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry, 199 const char *old_name) 200 { 201 struct path path = { parent->mnt, dentry }; 202 return tomoyo_check_1path_perm(tomoyo_domain(), 203 TOMOYO_TYPE_SYMLINK_ACL, 204 &path); 205 } 206 207 static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, 208 int mode, unsigned int dev) 209 { 210 struct path path = { parent->mnt, dentry }; 211 int type = TOMOYO_TYPE_CREATE_ACL; 212 213 switch (mode & S_IFMT) { 214 case S_IFCHR: 215 type = TOMOYO_TYPE_MKCHAR_ACL; 216 break; 217 case S_IFBLK: 218 type = TOMOYO_TYPE_MKBLOCK_ACL; 219 break; 220 case S_IFIFO: 221 type = TOMOYO_TYPE_MKFIFO_ACL; 222 break; 223 case S_IFSOCK: 224 type = TOMOYO_TYPE_MKSOCK_ACL; 225 break; 226 } 227 return tomoyo_check_1path_perm(tomoyo_domain(), 228 type, &path); 229 } 230 231 static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, 232 struct dentry *new_dentry) 233 { 234 struct path path1 = { new_dir->mnt, old_dentry }; 235 struct path path2 = { new_dir->mnt, new_dentry }; 236 return tomoyo_check_2path_perm(tomoyo_domain(), 237 TOMOYO_TYPE_LINK_ACL, 238 &path1, &path2); 239 } 240 241 static int tomoyo_path_rename(struct path *old_parent, 242 struct dentry *old_dentry, 243 struct path *new_parent, 244 struct dentry *new_dentry) 245 { 246 struct path path1 = { old_parent->mnt, old_dentry }; 247 struct path path2 = { new_parent->mnt, new_dentry }; 248 return tomoyo_check_2path_perm(tomoyo_domain(), 249 TOMOYO_TYPE_RENAME_ACL, 250 &path1, &path2); 251 } 252 253 static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, 254 unsigned long arg) 255 { 256 if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)) 257 return tomoyo_check_rewrite_permission(tomoyo_domain(), file); 258 return 0; 259 } 260 261 static int tomoyo_dentry_open(struct file *f, const struct cred *cred) 262 { 263 int flags = f->f_flags; 264 265 if ((flags + 1) & O_ACCMODE) 266 flags++; 267 flags |= f->f_flags & (O_APPEND | O_TRUNC); 268 /* Don't check read permission here if called from do_execve(). */ 269 if (current->in_execve) 270 return 0; 271 return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags); 272 } 273 274 /* 275 * tomoyo_security_ops is a "struct security_operations" which is used for 276 * registering TOMOYO. 277 */ 278 static struct security_operations tomoyo_security_ops = { 279 .name = "tomoyo", 280 .cred_alloc_blank = tomoyo_cred_alloc_blank, 281 .cred_prepare = tomoyo_cred_prepare, 282 .cred_transfer = tomoyo_cred_transfer, 283 .bprm_set_creds = tomoyo_bprm_set_creds, 284 .bprm_check_security = tomoyo_bprm_check_security, 285 #ifdef CONFIG_SYSCTL 286 .sysctl = tomoyo_sysctl, 287 #endif 288 .file_fcntl = tomoyo_file_fcntl, 289 .dentry_open = tomoyo_dentry_open, 290 .path_truncate = tomoyo_path_truncate, 291 .path_unlink = tomoyo_path_unlink, 292 .path_mkdir = tomoyo_path_mkdir, 293 .path_rmdir = tomoyo_path_rmdir, 294 .path_symlink = tomoyo_path_symlink, 295 .path_mknod = tomoyo_path_mknod, 296 .path_link = tomoyo_path_link, 297 .path_rename = tomoyo_path_rename, 298 }; 299 300 static int __init tomoyo_init(void) 301 { 302 struct cred *cred = (struct cred *) current_cred(); 303 304 if (!security_module_enable(&tomoyo_security_ops)) 305 return 0; 306 /* register ourselves with the security framework */ 307 if (register_security(&tomoyo_security_ops)) 308 panic("Failure registering TOMOYO Linux"); 309 printk(KERN_INFO "TOMOYO Linux initialized\n"); 310 cred->security = &tomoyo_kernel_domain; 311 tomoyo_realpath_init(); 312 return 0; 313 } 314 315 security_initcall(tomoyo_init); 316