tomoyo.c revision 937bf6133b21b16965f75223085f4314ae32b8eb
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 274static int tomoyo_file_ioctl(struct file *file, unsigned int cmd, 275 unsigned long arg) 276{ 277 return tomoyo_check_1path_perm(tomoyo_domain(), TOMOYO_TYPE_IOCTL_ACL, 278 &file->f_path); 279} 280 281static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt, 282 mode_t mode) 283{ 284 struct path path = { mnt, dentry }; 285 return tomoyo_check_1path_perm(tomoyo_domain(), TOMOYO_TYPE_CHMOD_ACL, 286 &path); 287} 288 289static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid) 290{ 291 int error = 0; 292 if (uid != (uid_t) -1) 293 error = tomoyo_check_1path_perm(tomoyo_domain(), 294 TOMOYO_TYPE_CHOWN_ACL, path); 295 if (!error && gid != (gid_t) -1) 296 error = tomoyo_check_1path_perm(tomoyo_domain(), 297 TOMOYO_TYPE_CHGRP_ACL, path); 298 return error; 299} 300 301static int tomoyo_path_chroot(struct path *path) 302{ 303 return tomoyo_check_1path_perm(tomoyo_domain(), TOMOYO_TYPE_CHROOT_ACL, 304 path); 305} 306 307static int tomoyo_sb_mount(char *dev_name, struct path *path, 308 char *type, unsigned long flags, void *data) 309{ 310 return tomoyo_check_1path_perm(tomoyo_domain(), TOMOYO_TYPE_MOUNT_ACL, 311 path); 312} 313 314static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) 315{ 316 struct path path = { mnt, mnt->mnt_root }; 317 return tomoyo_check_1path_perm(tomoyo_domain(), TOMOYO_TYPE_UMOUNT_ACL, 318 &path); 319} 320 321static int tomoyo_sb_pivotroot(struct path *old_path, struct path *new_path) 322{ 323 return tomoyo_check_2path_perm(tomoyo_domain(), 324 TOMOYO_TYPE_PIVOT_ROOT_ACL, 325 new_path, old_path); 326} 327 328/* 329 * tomoyo_security_ops is a "struct security_operations" which is used for 330 * registering TOMOYO. 331 */ 332static struct security_operations tomoyo_security_ops = { 333 .name = "tomoyo", 334 .cred_alloc_blank = tomoyo_cred_alloc_blank, 335 .cred_prepare = tomoyo_cred_prepare, 336 .cred_transfer = tomoyo_cred_transfer, 337 .bprm_set_creds = tomoyo_bprm_set_creds, 338 .bprm_check_security = tomoyo_bprm_check_security, 339#ifdef CONFIG_SYSCTL 340 .sysctl = tomoyo_sysctl, 341#endif 342 .file_fcntl = tomoyo_file_fcntl, 343 .dentry_open = tomoyo_dentry_open, 344 .path_truncate = tomoyo_path_truncate, 345 .path_unlink = tomoyo_path_unlink, 346 .path_mkdir = tomoyo_path_mkdir, 347 .path_rmdir = tomoyo_path_rmdir, 348 .path_symlink = tomoyo_path_symlink, 349 .path_mknod = tomoyo_path_mknod, 350 .path_link = tomoyo_path_link, 351 .path_rename = tomoyo_path_rename, 352 .file_ioctl = tomoyo_file_ioctl, 353 .path_chmod = tomoyo_path_chmod, 354 .path_chown = tomoyo_path_chown, 355 .path_chroot = tomoyo_path_chroot, 356 .sb_mount = tomoyo_sb_mount, 357 .sb_umount = tomoyo_sb_umount, 358 .sb_pivotroot = tomoyo_sb_pivotroot, 359}; 360 361static int __init tomoyo_init(void) 362{ 363 struct cred *cred = (struct cred *) current_cred(); 364 365 if (!security_module_enable(&tomoyo_security_ops)) 366 return 0; 367 /* register ourselves with the security framework */ 368 if (register_security(&tomoyo_security_ops)) 369 panic("Failure registering TOMOYO Linux"); 370 printk(KERN_INFO "TOMOYO Linux initialized\n"); 371 cred->security = &tomoyo_kernel_domain; 372 tomoyo_realpath_init(); 373 return 0; 374} 375 376security_initcall(tomoyo_init); 377