Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.32 315 lines 7.9 kB view raw
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 17static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) 18{ 19 new->security = NULL; 20 return 0; 21} 22 23static 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 34static 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 43static 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 71static 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 90static 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 */ 112static 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 148static 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 165static 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 173static 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 181static 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 190static 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 198static 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 207static 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 231static 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 241static 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 253static 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 261static 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 */ 278static 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 300static 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 315security_initcall(tomoyo_init);