-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
yaml --- r: 132615 b: refs/heads/master c: f743324 h: refs/heads/master i: 132613: 553bb20 132611: 7a46e86 132607: 305e076 v: v3
- Loading branch information
Kentaro Takeda
authored and
James Morris
committed
Feb 12, 2009
1 parent
55f8eb4
commit 3922c28
Showing
3 changed files
with
400 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
--- | ||
refs/heads/master: 26a2a1c9eb88d9aca8891575b3b986812e073872 | ||
refs/heads/master: f7433243770c77979c396b4c7449a10e9b3521db |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,293 @@ | ||
/* | ||
* security/tomoyo/tomoyo.c | ||
* | ||
* LSM hooks for TOMOYO Linux. | ||
* | ||
* Copyright (C) 2005-2009 NTT DATA CORPORATION | ||
* | ||
* Version: 2.2.0-pre 2009/02/01 | ||
* | ||
*/ | ||
|
||
#include <linux/security.h> | ||
#include "common.h" | ||
#include "tomoyo.h" | ||
#include "realpath.h" | ||
|
||
static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, | ||
gfp_t gfp) | ||
{ | ||
/* | ||
* Since "struct tomoyo_domain_info *" is a sharable pointer, | ||
* we don't need to duplicate. | ||
*/ | ||
new->security = old->security; | ||
return 0; | ||
} | ||
|
||
static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) | ||
{ | ||
/* | ||
* Do only if this function is called for the first time of an execve | ||
* operation. | ||
*/ | ||
if (bprm->cred_prepared) | ||
return 0; | ||
/* | ||
* Load policy if /sbin/tomoyo-init exists and /sbin/init is requested | ||
* for the first time. | ||
*/ | ||
if (!tomoyo_policy_loaded) | ||
tomoyo_load_policy(bprm->filename); | ||
/* | ||
* Tell tomoyo_bprm_check_security() is called for the first time of an | ||
* execve operation. | ||
*/ | ||
bprm->cred->security = NULL; | ||
return 0; | ||
} | ||
|
||
static int tomoyo_bprm_check_security(struct linux_binprm *bprm) | ||
{ | ||
struct tomoyo_domain_info *domain = bprm->cred->security; | ||
|
||
/* | ||
* Execute permission is checked against pathname passed to do_execve() | ||
* using current domain. | ||
*/ | ||
if (!domain) { | ||
struct tomoyo_domain_info *next_domain = NULL; | ||
int retval = tomoyo_find_next_domain(bprm, &next_domain); | ||
|
||
if (!retval) | ||
bprm->cred->security = next_domain; | ||
return retval; | ||
} | ||
/* | ||
* Read permission is checked against interpreters using next domain. | ||
* '1' is the result of open_to_namei_flags(O_RDONLY). | ||
*/ | ||
return tomoyo_check_open_permission(domain, &bprm->file->f_path, 1); | ||
} | ||
|
||
#ifdef CONFIG_SYSCTL | ||
|
||
static int tomoyo_prepend(char **buffer, int *buflen, const char *str) | ||
{ | ||
int namelen = strlen(str); | ||
|
||
if (*buflen < namelen) | ||
return -ENOMEM; | ||
*buflen -= namelen; | ||
*buffer -= namelen; | ||
memcpy(*buffer, str, namelen); | ||
return 0; | ||
} | ||
|
||
/** | ||
* tomoyo_sysctl_path - return the realpath of a ctl_table. | ||
* @table: pointer to "struct ctl_table". | ||
* | ||
* Returns realpath(3) of the @table on success. | ||
* Returns NULL on failure. | ||
* | ||
* This function uses tomoyo_alloc(), so the caller must call tomoyo_free() | ||
* if this function didn't return NULL. | ||
*/ | ||
static char *tomoyo_sysctl_path(struct ctl_table *table) | ||
{ | ||
int buflen = TOMOYO_MAX_PATHNAME_LEN; | ||
char *buf = tomoyo_alloc(buflen); | ||
char *end = buf + buflen; | ||
int error = -ENOMEM; | ||
|
||
if (!buf) | ||
return NULL; | ||
|
||
*--end = '\0'; | ||
buflen--; | ||
while (table) { | ||
char buf[32]; | ||
const char *sp = table->procname; | ||
|
||
if (!sp) { | ||
memset(buf, 0, sizeof(buf)); | ||
snprintf(buf, sizeof(buf) - 1, "=%d=", table->ctl_name); | ||
sp = buf; | ||
} | ||
if (tomoyo_prepend(&end, &buflen, sp) || | ||
tomoyo_prepend(&end, &buflen, "/")) | ||
goto out; | ||
table = table->parent; | ||
} | ||
if (tomoyo_prepend(&end, &buflen, "/proc/sys")) | ||
goto out; | ||
error = tomoyo_encode(buf, end - buf, end); | ||
out: | ||
if (!error) | ||
return buf; | ||
tomoyo_free(buf); | ||
return NULL; | ||
} | ||
|
||
static int tomoyo_sysctl(struct ctl_table *table, int op) | ||
{ | ||
int error; | ||
char *name; | ||
|
||
op &= MAY_READ | MAY_WRITE; | ||
if (!op) | ||
return 0; | ||
name = tomoyo_sysctl_path(table); | ||
if (!name) | ||
return -ENOMEM; | ||
error = tomoyo_check_file_perm(tomoyo_domain(), name, op); | ||
tomoyo_free(name); | ||
return error; | ||
} | ||
#endif | ||
|
||
static int tomoyo_path_truncate(struct path *path, loff_t length, | ||
unsigned int time_attrs) | ||
{ | ||
return tomoyo_check_1path_perm(tomoyo_domain(), | ||
TOMOYO_TYPE_TRUNCATE_ACL, | ||
path); | ||
} | ||
|
||
static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry) | ||
{ | ||
struct path path = { parent->mnt, dentry }; | ||
return tomoyo_check_1path_perm(tomoyo_domain(), | ||
TOMOYO_TYPE_UNLINK_ACL, | ||
&path); | ||
} | ||
|
||
static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, | ||
int mode) | ||
{ | ||
struct path path = { parent->mnt, dentry }; | ||
return tomoyo_check_1path_perm(tomoyo_domain(), | ||
TOMOYO_TYPE_MKDIR_ACL, | ||
&path); | ||
} | ||
|
||
static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) | ||
{ | ||
struct path path = { parent->mnt, dentry }; | ||
return tomoyo_check_1path_perm(tomoyo_domain(), | ||
TOMOYO_TYPE_RMDIR_ACL, | ||
&path); | ||
} | ||
|
||
static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry, | ||
const char *old_name) | ||
{ | ||
struct path path = { parent->mnt, dentry }; | ||
return tomoyo_check_1path_perm(tomoyo_domain(), | ||
TOMOYO_TYPE_SYMLINK_ACL, | ||
&path); | ||
} | ||
|
||
static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, | ||
int mode, unsigned int dev) | ||
{ | ||
struct path path = { parent->mnt, dentry }; | ||
int type = TOMOYO_TYPE_CREATE_ACL; | ||
|
||
switch (mode & S_IFMT) { | ||
case S_IFCHR: | ||
type = TOMOYO_TYPE_MKCHAR_ACL; | ||
break; | ||
case S_IFBLK: | ||
type = TOMOYO_TYPE_MKBLOCK_ACL; | ||
break; | ||
case S_IFIFO: | ||
type = TOMOYO_TYPE_MKFIFO_ACL; | ||
break; | ||
case S_IFSOCK: | ||
type = TOMOYO_TYPE_MKSOCK_ACL; | ||
break; | ||
} | ||
return tomoyo_check_1path_perm(tomoyo_domain(), | ||
type, &path); | ||
} | ||
|
||
static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, | ||
struct dentry *new_dentry) | ||
{ | ||
struct path path1 = { new_dir->mnt, old_dentry }; | ||
struct path path2 = { new_dir->mnt, new_dentry }; | ||
return tomoyo_check_2path_perm(tomoyo_domain(), | ||
TOMOYO_TYPE_LINK_ACL, | ||
&path1, &path2); | ||
} | ||
|
||
static int tomoyo_path_rename(struct path *old_parent, | ||
struct dentry *old_dentry, | ||
struct path *new_parent, | ||
struct dentry *new_dentry) | ||
{ | ||
struct path path1 = { old_parent->mnt, old_dentry }; | ||
struct path path2 = { new_parent->mnt, new_dentry }; | ||
return tomoyo_check_2path_perm(tomoyo_domain(), | ||
TOMOYO_TYPE_RENAME_ACL, | ||
&path1, &path2); | ||
} | ||
|
||
static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, | ||
unsigned long arg) | ||
{ | ||
if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)) | ||
return tomoyo_check_rewrite_permission(tomoyo_domain(), file); | ||
return 0; | ||
} | ||
|
||
static int tomoyo_dentry_open(struct file *f, const struct cred *cred) | ||
{ | ||
int flags = f->f_flags; | ||
|
||
if ((flags + 1) & O_ACCMODE) | ||
flags++; | ||
flags |= f->f_flags & (O_APPEND | O_TRUNC); | ||
/* Don't check read permission here if called from do_execve(). */ | ||
if (current->in_execve) | ||
return 0; | ||
return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags); | ||
} | ||
|
||
static struct security_operations tomoyo_security_ops = { | ||
.name = "tomoyo", | ||
.cred_prepare = tomoyo_cred_prepare, | ||
.bprm_set_creds = tomoyo_bprm_set_creds, | ||
.bprm_check_security = tomoyo_bprm_check_security, | ||
#ifdef CONFIG_SYSCTL | ||
.sysctl = tomoyo_sysctl, | ||
#endif | ||
.file_fcntl = tomoyo_file_fcntl, | ||
.dentry_open = tomoyo_dentry_open, | ||
.path_truncate = tomoyo_path_truncate, | ||
.path_unlink = tomoyo_path_unlink, | ||
.path_mkdir = tomoyo_path_mkdir, | ||
.path_rmdir = tomoyo_path_rmdir, | ||
.path_symlink = tomoyo_path_symlink, | ||
.path_mknod = tomoyo_path_mknod, | ||
.path_link = tomoyo_path_link, | ||
.path_rename = tomoyo_path_rename, | ||
}; | ||
|
||
static int __init tomoyo_init(void) | ||
{ | ||
struct cred *cred = (struct cred *) current_cred(); | ||
|
||
if (!security_module_enable(&tomoyo_security_ops)) | ||
return 0; | ||
/* register ourselves with the security framework */ | ||
if (register_security(&tomoyo_security_ops)) | ||
panic("Failure registering TOMOYO Linux"); | ||
printk(KERN_INFO "TOMOYO Linux initialized\n"); | ||
cred->security = &tomoyo_kernel_domain; | ||
return 0; | ||
} | ||
|
||
security_initcall(tomoyo_init); |
Oops, something went wrong.