mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 08:24:42 +01:00
Update kernel patches for 2.6.28
This commit is contained in:
parent
9d87470a60
commit
28ba83a313
63 changed files with 13390 additions and 0 deletions
506
kernel-patches/2.6.28/AppArmor-checkpatch.diff
Normal file
506
kernel-patches/2.6.28/AppArmor-checkpatch.diff
Normal file
|
@ -0,0 +1,506 @@
|
|||
|
||||
security/apparmor/apparmor.h | 5 +++
|
||||
security/apparmor/apparmorfs.c | 10 ++-----
|
||||
security/apparmor/inline.h | 2 -
|
||||
security/apparmor/list.c | 2 -
|
||||
security/apparmor/lsm.c | 35 ++++++++++++++-------------
|
||||
security/apparmor/main.c | 21 ++++++++--------
|
||||
security/apparmor/match.c | 8 ++----
|
||||
security/apparmor/match.h | 2 -
|
||||
security/apparmor/module_interface.c | 44 +++++++++++++----------------------
|
||||
security/apparmor/procattr.c | 5 +--
|
||||
10 files changed, 61 insertions(+), 73 deletions(-)
|
||||
|
||||
--- a/security/apparmor/apparmor.h
|
||||
+++ b/security/apparmor/apparmor.h
|
||||
@@ -297,6 +297,9 @@ enum aa_lock_class {
|
||||
aa_lock_task_release
|
||||
};
|
||||
|
||||
+/* apparmor/profiles */
|
||||
+extern struct seq_operations apparmorfs_profiles_op;
|
||||
+
|
||||
/* main.c */
|
||||
extern int alloc_default_namespace(void);
|
||||
extern void free_default_namespace(void);
|
||||
@@ -334,7 +337,7 @@ extern int aa_change_profile(const char
|
||||
extern struct aa_profile *__aa_replace_profile(struct task_struct *task,
|
||||
struct aa_profile *profile);
|
||||
extern struct aa_task_context *lock_task_and_profiles(struct task_struct *task,
|
||||
- struct aa_profile *profile);
|
||||
+ struct aa_profile *profile);
|
||||
extern void unlock_task_and_profiles(struct task_struct *task,
|
||||
struct aa_task_context *cxt,
|
||||
struct aa_profile *profile);
|
||||
--- a/security/apparmor/apparmorfs.c
|
||||
+++ b/security/apparmor/apparmorfs.c
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/seq_file.h>
|
||||
-#include <asm/uaccess.h>
|
||||
+#include <linux/uaccess.h>
|
||||
#include <linux/namei.h>
|
||||
|
||||
#include "apparmor.h"
|
||||
@@ -65,9 +65,6 @@ out:
|
||||
return data;
|
||||
}
|
||||
|
||||
-/* apparmor/profiles */
|
||||
-extern struct seq_operations apparmorfs_profiles_op;
|
||||
-
|
||||
static int aa_profiles_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open(file, &apparmorfs_profiles_op);
|
||||
@@ -236,8 +233,7 @@ int create_apparmorfs(void)
|
||||
return 0;
|
||||
|
||||
if (apparmor_dentry) {
|
||||
- AA_ERROR("%s: AppArmor securityfs already exists\n",
|
||||
- __FUNCTION__);
|
||||
+ AA_ERROR("%s: AppArmor securityfs already exists\n", __func__);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
@@ -245,7 +241,7 @@ int create_apparmorfs(void)
|
||||
if (IS_ERR(apparmor_dentry)) {
|
||||
error = PTR_ERR(apparmor_dentry);
|
||||
apparmor_dentry = NULL;
|
||||
- goto error;
|
||||
+ goto error;
|
||||
}
|
||||
error = aafs_create("profiles", 0440, &apparmorfs_profiles_fops);
|
||||
if (error)
|
||||
--- a/security/apparmor/inline.h
|
||||
+++ b/security/apparmor/inline.h
|
||||
@@ -213,7 +213,7 @@ static inline void lock_both_profiles(st
|
||||
* gives us RCU reader safety.
|
||||
*/
|
||||
static inline void unlock_both_profiles(struct aa_profile *profile1,
|
||||
- struct aa_profile *profile2)
|
||||
+ struct aa_profile *profile2)
|
||||
{
|
||||
/* Unlock the two profiles. */
|
||||
if (!profile1 || profile1 == profile2) {
|
||||
--- a/security/apparmor/list.c
|
||||
+++ b/security/apparmor/list.c
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
/* list of profile namespaces and lock */
|
||||
LIST_HEAD(profile_ns_list);
|
||||
-rwlock_t profile_ns_list_lock = RW_LOCK_UNLOCKED;
|
||||
+DEFINE_RWLOCK(profile_ns_list_lock);
|
||||
|
||||
/**
|
||||
* __aa_find_namespace - look up a profile namespace on the namespace list
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "inline.h"
|
||||
|
||||
/* Flag indicating whether initialization completed */
|
||||
-int apparmor_initialized = 0;
|
||||
+int apparmor_initialized;
|
||||
|
||||
static int param_set_aabool(const char *val, struct kernel_param *kp);
|
||||
static int param_get_aabool(char *buffer, struct kernel_param *kp);
|
||||
@@ -43,22 +43,22 @@ static int param_get_aauint(char *buffer
|
||||
* Value is also togglable per profile and referenced when global value is
|
||||
* enforce.
|
||||
*/
|
||||
-int apparmor_complain = 0;
|
||||
+int apparmor_complain;
|
||||
module_param_named(complain, apparmor_complain, aabool, S_IRUSR | S_IWUSR);
|
||||
MODULE_PARM_DESC(apparmor_complain, "Toggle AppArmor complain mode");
|
||||
|
||||
/* Debug mode */
|
||||
-int apparmor_debug = 0;
|
||||
+int apparmor_debug;
|
||||
module_param_named(debug, apparmor_debug, aabool, S_IRUSR | S_IWUSR);
|
||||
MODULE_PARM_DESC(apparmor_debug, "Toggle AppArmor debug mode");
|
||||
|
||||
/* Audit mode */
|
||||
-int apparmor_audit = 0;
|
||||
+int apparmor_audit;
|
||||
module_param_named(audit, apparmor_audit, aabool, S_IRUSR | S_IWUSR);
|
||||
MODULE_PARM_DESC(apparmor_audit, "Toggle AppArmor audit mode");
|
||||
|
||||
/* Syscall logging mode */
|
||||
-int apparmor_logsyscall = 0;
|
||||
+int apparmor_logsyscall;
|
||||
module_param_named(logsyscall, apparmor_logsyscall, aabool, S_IRUSR | S_IWUSR);
|
||||
MODULE_PARM_DESC(apparmor_logsyscall, "Toggle AppArmor logsyscall mode");
|
||||
|
||||
@@ -117,7 +117,6 @@ static int param_get_aauint(char *buffer
|
||||
/* allow run time disabling of apparmor */
|
||||
static int param_set_aa_enabled(const char *val, struct kernel_param *kp)
|
||||
{
|
||||
- char *endp;
|
||||
unsigned long l;
|
||||
|
||||
if (!apparmor_initialized) {
|
||||
@@ -134,8 +133,7 @@ static int param_set_aa_enabled(const ch
|
||||
if (!val)
|
||||
return -EINVAL;
|
||||
|
||||
- l = simple_strtoul(val, &endp, 0);
|
||||
- if (endp == val || l != 0)
|
||||
+ if (strict_strtoul(val, 0, &l) || l != 0)
|
||||
return -EINVAL;
|
||||
|
||||
apparmor_enabled = 0;
|
||||
@@ -238,7 +236,7 @@ static int apparmor_sysctl(struct ctl_ta
|
||||
mask |= MAY_WRITE;
|
||||
|
||||
error = -ENOMEM;
|
||||
- buffer = (char*)__get_free_page(GFP_KERNEL);
|
||||
+ buffer = (char *)__get_free_page(GFP_KERNEL);
|
||||
if (!buffer)
|
||||
goto out;
|
||||
name = sysctl_pathname(table, buffer, PAGE_SIZE);
|
||||
@@ -271,7 +269,7 @@ static int apparmor_bprm_secureexec(stru
|
||||
|
||||
if (!ret && (unsigned long)bprm->security & AA_SECURE_EXEC_NEEDED) {
|
||||
AA_DEBUG("%s: secureexec required for %s\n",
|
||||
- __FUNCTION__, bprm->filename);
|
||||
+ __func__, bprm->filename);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
@@ -522,7 +520,7 @@ static int apparmor_inode_removexattr(st
|
||||
static int aa_file_permission(const char *op, struct file *file, int mask)
|
||||
{
|
||||
struct aa_profile *profile;
|
||||
- struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
|
||||
+ struct aa_profile *file_profile = file->f_security;
|
||||
int error = 0;
|
||||
|
||||
if (!file_profile)
|
||||
@@ -559,7 +557,7 @@ static int apparmor_file_permission(stru
|
||||
aa_mask_permissions(mask));
|
||||
}
|
||||
|
||||
-static inline int apparmor_file_lock (struct file *file, unsigned int cmd)
|
||||
+static inline int apparmor_file_lock(struct file *file, unsigned int cmd)
|
||||
{
|
||||
int mask = AA_MAY_LOCK;
|
||||
if (cmd == F_WRLCK)
|
||||
@@ -580,7 +578,7 @@ static int apparmor_file_alloc_security(
|
||||
|
||||
static void apparmor_file_free_security(struct file *file)
|
||||
{
|
||||
- struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
|
||||
+ struct aa_profile *file_profile = file->f_security;
|
||||
|
||||
aa_put_profile(file_profile);
|
||||
}
|
||||
@@ -967,17 +965,20 @@ static int __init apparmor_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if ((error = create_apparmorfs())) {
|
||||
+ error = create_apparmorfs();
|
||||
+ if (error) {
|
||||
AA_ERROR("Unable to activate AppArmor filesystem\n");
|
||||
goto createfs_out;
|
||||
}
|
||||
|
||||
- if ((error = alloc_default_namespace())){
|
||||
+ error = alloc_default_namespace();
|
||||
+ if (error) {
|
||||
AA_ERROR("Unable to allocate default profile namespace\n");
|
||||
goto alloc_out;
|
||||
}
|
||||
|
||||
- if ((error = register_security(&apparmor_ops))) {
|
||||
+ error = register_security(&apparmor_ops);
|
||||
+ if (error) {
|
||||
AA_ERROR("Unable to register AppArmor\n");
|
||||
goto register_security_out;
|
||||
}
|
||||
@@ -995,7 +996,7 @@ register_security_out:
|
||||
free_default_namespace();
|
||||
|
||||
alloc_out:
|
||||
- destroy_apparmorfs();
|
||||
+ destroy_apparmorfs();
|
||||
|
||||
createfs_out:
|
||||
return error;
|
||||
--- a/security/apparmor/main.c
|
||||
+++ b/security/apparmor/main.c
|
||||
@@ -416,7 +416,7 @@ static int aa_link_denied(struct aa_prof
|
||||
*
|
||||
* If the link has 'x', an exact match of all the execute flags
|
||||
* must match.
|
||||
- */
|
||||
+ */
|
||||
denied_mask |= ~l_mode & link_mask;
|
||||
|
||||
t_mode = aa_match(profile->file_rules, target, NULL);
|
||||
@@ -445,8 +445,10 @@ static int aa_link_denied(struct aa_prof
|
||||
(x & AA_USER_EXEC_TYPE) != (t_x & AA_USER_EXEC_TYPE))
|
||||
denied_mask = AA_USER_EXEC | (l_x & AA_USER_EXEC_TYPE);
|
||||
if ((l_mode & AA_OTHER_EXEC) &&
|
||||
- (x & AA_OTHER_EXEC_TYPE) != (t_x & AA_OTHER_EXEC_TYPE))
|
||||
- denied_mask = AA_OTHER_EXEC | (l_x & AA_OTHER_EXEC_TYPE);
|
||||
+ (x & AA_OTHER_EXEC_TYPE) != (t_x & AA_OTHER_EXEC_TYPE)) {
|
||||
+ denied_mask =
|
||||
+ AA_OTHER_EXEC | (l_x & AA_OTHER_EXEC_TYPE);
|
||||
+ }
|
||||
}
|
||||
|
||||
return denied_mask;
|
||||
@@ -866,7 +868,7 @@ int aa_revalidate_sk(struct sock *sk, ch
|
||||
/* this is some debugging code to flush out the network hooks that
|
||||
that are called in interrupt context */
|
||||
if (in_interrupt()) {
|
||||
- printk("AppArmor Debug: Hook being called from interrupt context\n");
|
||||
+ printk(KERN_WARNING "AppArmor Debug: Hook being called from interrupt context\n");
|
||||
dump_stack();
|
||||
return 0;
|
||||
}
|
||||
@@ -1019,7 +1021,7 @@ repeat:
|
||||
}
|
||||
|
||||
static struct aa_profile *
|
||||
-aa_register_find(struct aa_profile *profile, const char* ns_name,
|
||||
+aa_register_find(struct aa_profile *profile, const char *ns_name,
|
||||
const char *name, int mandatory, int complain,
|
||||
struct aa_audit *sa)
|
||||
{
|
||||
@@ -1053,7 +1055,7 @@ aa_register_find(struct aa_profile *prof
|
||||
|
||||
if (new_profile) {
|
||||
AA_DEBUG("%s: setting profile %s\n",
|
||||
- __FUNCTION__, new_profile->name);
|
||||
+ __func__, new_profile->name);
|
||||
} else if (mandatory && profile) {
|
||||
sa->info = "mandatory profile missing";
|
||||
sa->denied_mask = sa->request_mask; /* shifted MAY_EXEC */
|
||||
@@ -1072,8 +1074,7 @@ aa_register_find(struct aa_profile *prof
|
||||
* is unconfined, pix, nix.
|
||||
*/
|
||||
AA_DEBUG("%s: No profile found for exec image '%s'\n",
|
||||
- __FUNCTION__,
|
||||
- name);
|
||||
+ __func__, name);
|
||||
}
|
||||
if (ns_ref)
|
||||
aa_put_namespace(ns);
|
||||
@@ -1158,7 +1159,7 @@ int aa_register(struct linux_binprm *bpr
|
||||
int exec_mode, complain = 0, shift;
|
||||
struct aa_audit sa;
|
||||
|
||||
- AA_DEBUG("%s\n", __FUNCTION__);
|
||||
+ AA_DEBUG("%s\n", __func__);
|
||||
|
||||
profile = aa_get_profile(current);
|
||||
|
||||
@@ -1266,7 +1267,7 @@ repeat:
|
||||
unsigned long bprm_flags;
|
||||
|
||||
bprm_flags = AA_SECURE_EXEC_NEEDED;
|
||||
- bprm->security = (void*)
|
||||
+ bprm->security = (void *)
|
||||
((unsigned long)bprm->security | bprm_flags);
|
||||
}
|
||||
|
||||
--- a/security/apparmor/match.c
|
||||
+++ b/security/apparmor/match.c
|
||||
@@ -82,7 +82,7 @@ int unpack_dfa(struct aa_dfa *dfa, void
|
||||
if (!table)
|
||||
goto fail;
|
||||
|
||||
- switch(table->td_id) {
|
||||
+ switch (table->td_id) {
|
||||
case YYTD_ID_ACCEPT:
|
||||
case YYTD_ID_ACCEPT2:
|
||||
case YYTD_ID_BASE:
|
||||
@@ -115,10 +115,8 @@ int unpack_dfa(struct aa_dfa *dfa, void
|
||||
|
||||
fail:
|
||||
for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
|
||||
- if (dfa->tables[i]) {
|
||||
- kfree(dfa->tables[i]);
|
||||
- dfa->tables[i] = NULL;
|
||||
- }
|
||||
+ kfree(dfa->tables[i]);
|
||||
+ dfa->tables[i] = NULL;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
--- a/security/apparmor/match.h
|
||||
+++ b/security/apparmor/match.h
|
||||
@@ -61,7 +61,7 @@ struct table_header {
|
||||
#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK - 1]->td_data))
|
||||
#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC - 1]->td_data))
|
||||
#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT - 1]->td_data))
|
||||
-#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2 -1]->td_data))
|
||||
+#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2 - 1]->td_data))
|
||||
|
||||
struct aa_dfa {
|
||||
struct table_header *tables[YYTD_ID_NXT];
|
||||
--- a/security/apparmor/module_interface.c
|
||||
+++ b/security/apparmor/module_interface.c
|
||||
@@ -219,7 +219,7 @@ static size_t aa_is_blob(struct aa_ext *
|
||||
size = le32_to_cpu(get_unaligned((u32 *)e->pos));
|
||||
e->pos += sizeof(u32);
|
||||
if (aa_inbounds(e, (size_t) size)) {
|
||||
- * blob = e->pos;
|
||||
+ *blob = e->pos;
|
||||
e->pos += size;
|
||||
return size;
|
||||
}
|
||||
@@ -237,8 +237,8 @@ static int aa_is_dynstring(struct aa_ext
|
||||
*string = NULL;
|
||||
if (aa_is_nameX(e, AA_STRING, name) &&
|
||||
(size = aa_is_u16_chunk(e, &src_str))) {
|
||||
- char *str;
|
||||
- if (!(str = kmalloc(size, GFP_KERNEL)))
|
||||
+ char *str = kmalloc(size, GFP_KERNEL);
|
||||
+ if (!str)
|
||||
goto fail;
|
||||
memcpy(str, src_str, size);
|
||||
*string = str;
|
||||
@@ -495,9 +495,8 @@ static int aa_verify_header(struct aa_ex
|
||||
}
|
||||
|
||||
/* read the namespace if present */
|
||||
- if (!aa_is_dynstring(e, &e->ns_name, "namespace")) {
|
||||
+ if (!aa_is_dynstring(e, &e->ns_name, "namespace"))
|
||||
e->ns_name = NULL;
|
||||
- }
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -592,11 +591,8 @@ static inline void task_replace(struct t
|
||||
{
|
||||
struct aa_task_context *cxt = aa_task_context(task);
|
||||
|
||||
- AA_DEBUG("%s: replacing profile for task %d "
|
||||
- "profile=%s (%p)\n",
|
||||
- __FUNCTION__,
|
||||
- cxt->task->pid,
|
||||
- cxt->profile->name, cxt->profile);
|
||||
+ AA_DEBUG("%s: replacing profile for task %d profile=%s (%p)\n",
|
||||
+ __func__, cxt->task->pid, cxt->profile->name, cxt->profile);
|
||||
|
||||
aa_change_task_context(task, new_cxt, new_profile, cxt->cookie,
|
||||
cxt->previous_profile);
|
||||
@@ -797,9 +793,7 @@ noent:
|
||||
*/
|
||||
void free_aa_namespace_kref(struct kref *kref)
|
||||
{
|
||||
- struct aa_namespace *ns=container_of(kref, struct aa_namespace, count);
|
||||
-
|
||||
- free_aa_namespace(ns);
|
||||
+ free_aa_namespace(container_of(kref, struct aa_namespace, count));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -812,7 +806,7 @@ struct aa_namespace *alloc_aa_namespace(
|
||||
struct aa_namespace *ns;
|
||||
|
||||
ns = kzalloc(sizeof(*ns), GFP_KERNEL);
|
||||
- AA_DEBUG("%s(%p)\n", __FUNCTION__, ns);
|
||||
+ AA_DEBUG("%s(%p)\n", __func__, ns);
|
||||
if (ns) {
|
||||
ns->name = name;
|
||||
INIT_LIST_HEAD(&ns->list);
|
||||
@@ -854,7 +848,7 @@ struct aa_namespace *alloc_aa_namespace(
|
||||
*/
|
||||
void free_aa_namespace(struct aa_namespace *ns)
|
||||
{
|
||||
- AA_DEBUG("%s(%p)\n", __FUNCTION__, ns);
|
||||
+ AA_DEBUG("%s(%p)\n", __func__, ns);
|
||||
|
||||
if (!ns)
|
||||
return;
|
||||
@@ -863,15 +857,12 @@ void free_aa_namespace(struct aa_namespa
|
||||
if (!list_empty(&ns->profiles)) {
|
||||
AA_ERROR("%s: internal error, "
|
||||
"namespace '%s' still contains profiles\n",
|
||||
- __FUNCTION__,
|
||||
- ns->name);
|
||||
+ __func__, ns->name);
|
||||
BUG();
|
||||
}
|
||||
if (!list_empty(&ns->list)) {
|
||||
- AA_ERROR("%s: internal error, "
|
||||
- "namespace '%s' still on list\n",
|
||||
- __FUNCTION__,
|
||||
- ns->name);
|
||||
+ AA_ERROR("%s: internal error, namespace '%s' still on list\n",
|
||||
+ __func__, ns->name);
|
||||
BUG();
|
||||
}
|
||||
/* null_complain_profile doesn't contribute to ns ref counting */
|
||||
@@ -887,7 +878,7 @@ void free_aa_namespace(struct aa_namespa
|
||||
*/
|
||||
void free_aa_profile_kref(struct kref *kref)
|
||||
{
|
||||
- struct aa_profile *p=container_of(kref, struct aa_profile, count);
|
||||
+ struct aa_profile *p = container_of(kref, struct aa_profile, count);
|
||||
|
||||
free_aa_profile(p);
|
||||
}
|
||||
@@ -901,7 +892,7 @@ struct aa_profile *alloc_aa_profile(void
|
||||
struct aa_profile *profile;
|
||||
|
||||
profile = kzalloc(sizeof(*profile), GFP_KERNEL);
|
||||
- AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
|
||||
+ AA_DEBUG("%s(%p)\n", __func__, profile);
|
||||
if (profile) {
|
||||
INIT_LIST_HEAD(&profile->list);
|
||||
kref_init(&profile->count);
|
||||
@@ -923,7 +914,7 @@ struct aa_profile *alloc_aa_profile(void
|
||||
*/
|
||||
void free_aa_profile(struct aa_profile *profile)
|
||||
{
|
||||
- AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
|
||||
+ AA_DEBUG("%s(%p)\n", __func__, profile);
|
||||
|
||||
if (!profile)
|
||||
return;
|
||||
@@ -932,8 +923,7 @@ void free_aa_profile(struct aa_profile *
|
||||
if (!list_empty(&profile->list)) {
|
||||
AA_ERROR("%s: internal error, "
|
||||
"profile '%s' still on global list\n",
|
||||
- __FUNCTION__,
|
||||
- profile->name);
|
||||
+ __func__, profile->name);
|
||||
BUG();
|
||||
}
|
||||
aa_put_namespace(profile->ns);
|
||||
@@ -941,7 +931,7 @@ void free_aa_profile(struct aa_profile *
|
||||
aa_match_free(profile->file_rules);
|
||||
|
||||
if (profile->name) {
|
||||
- AA_DEBUG("%s: %s\n", __FUNCTION__, profile->name);
|
||||
+ AA_DEBUG("%s: %s\n", __func__, profile->name);
|
||||
kfree(profile->name);
|
||||
}
|
||||
|
||||
--- a/security/apparmor/procattr.c
|
||||
+++ b/security/apparmor/procattr.c
|
||||
@@ -88,7 +88,7 @@ int aa_setprocattr_changehat(char *args)
|
||||
}
|
||||
|
||||
AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
|
||||
- __FUNCTION__, cookie, hat ? hat : NULL);
|
||||
+ __func__, cookie, hat ? hat : NULL);
|
||||
|
||||
return aa_change_hat(hat, cookie);
|
||||
}
|
||||
@@ -121,8 +121,7 @@ int aa_setprocattr_setprofile(struct tas
|
||||
sa.gfp_mask = GFP_KERNEL;
|
||||
sa.task = task->pid;
|
||||
|
||||
- AA_DEBUG("%s: current %d\n",
|
||||
- __FUNCTION__, current->pid);
|
||||
+ AA_DEBUG("%s: current %d\n", __func__, current->pid);
|
||||
|
||||
name = args;
|
||||
if (args[0] != '/') {
|
260
kernel-patches/2.6.28/AppArmor-misc-cleanups.diff
Normal file
260
kernel-patches/2.6.28/AppArmor-misc-cleanups.diff
Normal file
|
@ -0,0 +1,260 @@
|
|||
security/apparmor/Kconfig | 1 +
|
||||
security/apparmor/apparmor.h | 7 +++----
|
||||
security/apparmor/inline.h | 4 ++--
|
||||
security/apparmor/list.c | 2 ++
|
||||
security/apparmor/lsm.c | 22 ++++++----------------
|
||||
security/apparmor/main.c | 5 +++--
|
||||
security/apparmor/match.c | 5 +++--
|
||||
security/apparmor/module_interface.c | 13 ++++++-------
|
||||
8 files changed, 26 insertions(+), 33 deletions(-)
|
||||
|
||||
--- a/security/apparmor/Kconfig
|
||||
+++ b/security/apparmor/Kconfig
|
||||
@@ -3,6 +3,7 @@ config SECURITY_APPARMOR
|
||||
depends on SECURITY
|
||||
depends on SECURITY_NETWORK
|
||||
select AUDIT
|
||||
+ default n
|
||||
help
|
||||
This enables the AppArmor security module.
|
||||
Required userspace tools (if they are not included in your
|
||||
--- a/security/apparmor/apparmor.h
|
||||
+++ b/security/apparmor/apparmor.h
|
||||
@@ -214,9 +214,9 @@ struct aa_profile {
|
||||
char **exec_table;
|
||||
struct aa_dfa *file_rules;
|
||||
struct {
|
||||
- int hat;
|
||||
- int complain;
|
||||
- int audit;
|
||||
+ u32 hat;
|
||||
+ u32 complain;
|
||||
+ u32 audit;
|
||||
} flags;
|
||||
int isstale;
|
||||
|
||||
@@ -310,7 +310,6 @@ void aa_audit_status(struct aa_profile *
|
||||
int aa_audit_reject(struct aa_profile *profile, struct aa_audit *sa);
|
||||
extern int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp,
|
||||
const char *);
|
||||
-extern int aa_audit(struct aa_profile *profile, struct aa_audit *);
|
||||
|
||||
extern int aa_attr(struct aa_profile *profile, struct dentry *dentry,
|
||||
struct vfsmount *mnt, struct iattr *iattr);
|
||||
--- a/security/apparmor/inline.h
|
||||
+++ b/security/apparmor/inline.h
|
||||
@@ -21,7 +21,7 @@ static inline int mediated_filesystem(st
|
||||
|
||||
static inline struct aa_task_context *aa_task_context(struct task_struct *task)
|
||||
{
|
||||
- return (struct aa_task_context *) rcu_dereference(task->security);
|
||||
+ return rcu_dereference(task->security);
|
||||
}
|
||||
|
||||
static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
|
||||
@@ -91,7 +91,7 @@ static inline struct aa_profile *aa_get_
|
||||
static inline struct aa_profile *aa_find_profile(struct aa_namespace *ns,
|
||||
const char *name)
|
||||
{
|
||||
- struct aa_profile *profile = NULL;
|
||||
+ struct aa_profile *profile;
|
||||
|
||||
read_lock(&ns->lock);
|
||||
profile = aa_dup_profile(__aa_find_profile(name, &ns->profiles));
|
||||
--- a/security/apparmor/list.c
|
||||
+++ b/security/apparmor/list.c
|
||||
@@ -112,6 +112,7 @@ static struct aa_profile *next_profile(s
|
||||
}
|
||||
|
||||
static void *p_start(struct seq_file *f, loff_t *pos)
|
||||
+ __acquires(profile_ns_list_lock)
|
||||
{
|
||||
struct aa_namespace *ns;
|
||||
loff_t l = *pos;
|
||||
@@ -144,6 +145,7 @@ static void *p_next(struct seq_file *f,
|
||||
}
|
||||
|
||||
static void p_stop(struct seq_file *f, void *p)
|
||||
+ __releases(profile_ns_list_lock)
|
||||
{
|
||||
struct aa_profile *profile = (struct aa_profile *) p;
|
||||
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/security.h>
|
||||
-#include <linux/module.h>
|
||||
+#include <linux/moduleparam.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/mount.h>
|
||||
@@ -45,27 +45,21 @@ static int param_get_aauint(char *buffer
|
||||
*/
|
||||
int apparmor_complain;
|
||||
module_param_named(complain, apparmor_complain, aabool, S_IRUSR | S_IWUSR);
|
||||
-MODULE_PARM_DESC(apparmor_complain, "Toggle AppArmor complain mode");
|
||||
|
||||
/* Debug mode */
|
||||
int apparmor_debug;
|
||||
module_param_named(debug, apparmor_debug, aabool, S_IRUSR | S_IWUSR);
|
||||
-MODULE_PARM_DESC(apparmor_debug, "Toggle AppArmor debug mode");
|
||||
|
||||
/* Audit mode */
|
||||
int apparmor_audit;
|
||||
module_param_named(audit, apparmor_audit, aabool, S_IRUSR | S_IWUSR);
|
||||
-MODULE_PARM_DESC(apparmor_audit, "Toggle AppArmor audit mode");
|
||||
-
|
||||
/* Syscall logging mode */
|
||||
int apparmor_logsyscall;
|
||||
module_param_named(logsyscall, apparmor_logsyscall, aabool, S_IRUSR | S_IWUSR);
|
||||
-MODULE_PARM_DESC(apparmor_logsyscall, "Toggle AppArmor logsyscall mode");
|
||||
|
||||
/* Maximum pathname length before accesses will start getting rejected */
|
||||
unsigned int apparmor_path_max = 2 * PATH_MAX;
|
||||
module_param_named(path_max, apparmor_path_max, aauint, S_IRUSR | S_IWUSR);
|
||||
-MODULE_PARM_DESC(apparmor_path_max, "Maximum pathname length allowed");
|
||||
|
||||
/* Boot time disable flag */
|
||||
#ifdef CONFIG_SECURITY_APPARMOR_DISABLE
|
||||
@@ -74,10 +68,9 @@ MODULE_PARM_DESC(apparmor_path_max, "Max
|
||||
#define AA_ENABLED_PERMS 0400
|
||||
#endif
|
||||
static int param_set_aa_enabled(const char *val, struct kernel_param *kp);
|
||||
-unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
|
||||
+static unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
|
||||
module_param_call(enabled, param_set_aa_enabled, param_get_aauint,
|
||||
&apparmor_enabled, AA_ENABLED_PERMS);
|
||||
-MODULE_PARM_DESC(apparmor_enabled, "Enable/Disable Apparmor on boot");
|
||||
|
||||
static int __init apparmor_enabled_setup(char *str)
|
||||
{
|
||||
@@ -557,7 +550,7 @@ static int apparmor_file_permission(stru
|
||||
aa_mask_permissions(mask));
|
||||
}
|
||||
|
||||
-static inline int apparmor_file_lock(struct file *file, unsigned int cmd)
|
||||
+static int apparmor_file_lock(struct file *file, unsigned int cmd)
|
||||
{
|
||||
int mask = AA_MAY_LOCK;
|
||||
if (cmd == F_WRLCK)
|
||||
@@ -583,8 +576,8 @@ static void apparmor_file_free_security(
|
||||
aa_put_profile(file_profile);
|
||||
}
|
||||
|
||||
-static inline int aa_mmap(struct file *file, const char *operation,
|
||||
- unsigned long prot, unsigned long flags)
|
||||
+static int aa_mmap(struct file *file, const char *operation,
|
||||
+ unsigned long prot, unsigned long flags)
|
||||
{
|
||||
struct dentry *dentry;
|
||||
int mask = 0;
|
||||
@@ -883,7 +876,7 @@ static int apparmor_task_setrlimit(unsig
|
||||
return error;
|
||||
}
|
||||
|
||||
-struct security_operations apparmor_ops = {
|
||||
+static struct security_operations apparmor_ops = {
|
||||
.name = "apparmor",
|
||||
.ptrace_may_access = apparmor_ptrace_may_access,
|
||||
.ptrace_traceme = apparmor_ptrace_traceme,
|
||||
@@ -1029,6 +1022,3 @@ void apparmor_disable(void)
|
||||
info_message("AppArmor protection removed");
|
||||
}
|
||||
|
||||
-MODULE_DESCRIPTION("AppArmor process confinement");
|
||||
-MODULE_AUTHOR("Novell/Immunix, http://bugs.opensuse.org");
|
||||
-MODULE_LICENSE("GPL");
|
||||
--- a/security/apparmor/main.c
|
||||
+++ b/security/apparmor/main.c
|
||||
@@ -299,7 +299,7 @@ int aa_audit_reject(struct aa_profile *p
|
||||
* @profile: profile to check against
|
||||
* @sa: audit event
|
||||
*/
|
||||
-int aa_audit(struct aa_profile *profile, struct aa_audit *sa)
|
||||
+static int aa_audit(struct aa_profile *profile, struct aa_audit *sa)
|
||||
{
|
||||
int type = AUDIT_APPARMOR_DENIED;
|
||||
struct audit_context *audit_cxt;
|
||||
@@ -520,7 +520,8 @@ static char *new_compound_name(const cha
|
||||
sprintf(name, "%s//%s", n1, n2);
|
||||
return name;
|
||||
}
|
||||
-static inline void aa_put_name_buffer(char *buffer)
|
||||
+
|
||||
+static void aa_put_name_buffer(char *buffer)
|
||||
{
|
||||
kfree(buffer);
|
||||
}
|
||||
--- a/security/apparmor/match.c
|
||||
+++ b/security/apparmor/match.c
|
||||
@@ -226,8 +226,9 @@ void aa_match_free(struct aa_dfa *dfa)
|
||||
* but that would require traversing the string twice and be slightly
|
||||
* slower.
|
||||
*/
|
||||
-unsigned int aa_dfa_next_state_len(struct aa_dfa *dfa, unsigned int start,
|
||||
- const char *str, int len)
|
||||
+static unsigned int aa_dfa_next_state_len(struct aa_dfa *dfa,
|
||||
+ unsigned int start,
|
||||
+ const char *str, int len)
|
||||
{
|
||||
u16 *def = DEFAULT_TABLE(dfa);
|
||||
u32 *base = BASE_TABLE(dfa);
|
||||
--- a/security/apparmor/module_interface.c
|
||||
+++ b/security/apparmor/module_interface.c
|
||||
@@ -61,7 +61,7 @@ struct aa_ext {
|
||||
char *ns_name;
|
||||
};
|
||||
|
||||
-static inline int aa_inbounds(struct aa_ext *e, size_t size)
|
||||
+static int aa_inbounds(struct aa_ext *e, size_t size)
|
||||
{
|
||||
return (size <= e->end - e->pos);
|
||||
}
|
||||
@@ -94,7 +94,7 @@ fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static inline int aa_is_X(struct aa_ext *e, enum aa_code code)
|
||||
+static int aa_is_X(struct aa_ext *e, enum aa_code code)
|
||||
{
|
||||
if (!aa_inbounds(e, 1))
|
||||
return 0;
|
||||
@@ -369,7 +369,7 @@ fail:
|
||||
static struct aa_profile *aa_unpack_profile(struct aa_ext *e,
|
||||
struct aa_audit *sa)
|
||||
{
|
||||
- struct aa_profile *profile = NULL;
|
||||
+ struct aa_profile *profile;
|
||||
size_t size = 0;
|
||||
int i, error = -EPROTO;
|
||||
|
||||
@@ -465,8 +465,7 @@ fail:
|
||||
sa->info = "failed to unpack profile";
|
||||
aa_audit_status(NULL, sa);
|
||||
|
||||
- if (profile)
|
||||
- free_aa_profile(profile);
|
||||
+ free_aa_profile(profile);
|
||||
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
@@ -508,7 +507,7 @@ static int aa_verify_header(struct aa_ex
|
||||
*/
|
||||
ssize_t aa_add_profile(void *data, size_t size)
|
||||
{
|
||||
- struct aa_profile *profile = NULL;
|
||||
+ struct aa_profile *profile;
|
||||
struct aa_namespace *ns = NULL;
|
||||
struct aa_ext e = {
|
||||
.start = data,
|
||||
@@ -585,7 +584,7 @@ ssize_t aa_add_profile(void *data, size_
|
||||
* @new_cxt: new aa_task_context to do replacement with
|
||||
* @new_profile: new profile
|
||||
*/
|
||||
-static inline void task_replace(struct task_struct *task,
|
||||
+static void task_replace(struct task_struct *task,
|
||||
struct aa_task_context *new_cxt,
|
||||
struct aa_profile *new_profile)
|
||||
{
|
201
kernel-patches/2.6.28/add-path_permission.diff
Normal file
201
kernel-patches/2.6.28/add-path_permission.diff
Normal file
|
@ -0,0 +1,201 @@
|
|||
From: Jeff Mahoney <jeffm@suse.com>
|
||||
Subject: [PATCH] vfs: introduce path_permission()
|
||||
|
||||
2.6.27 eliminated the nameidata parameter from permission and replaced
|
||||
several call sites with inode_permission. This keeps the information
|
||||
required by AppArmor from reaching it.
|
||||
|
||||
The following patch factors out the permission assessment part of
|
||||
inode_permission into __inode_permission and adds a path_permission
|
||||
function that takes a struct path instead of a struct inode and passes
|
||||
it to security_path_permission instead of security_inode_permission.
|
||||
|
||||
All of the call sites that had access to a struct path whether by
|
||||
itself or via a file or nameidata (and used it) in 2.6.26 are changed
|
||||
to use the path_permission call.
|
||||
|
||||
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
fs/inotify_user.c | 2 +-
|
||||
fs/namei.c | 32 ++++++++++++++++++++++++--------
|
||||
fs/open.c | 10 +++++-----
|
||||
include/linux/fs.h | 5 +++++
|
||||
4 files changed, 35 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/fs/inotify_user.c
|
||||
+++ b/fs/inotify_user.c
|
||||
@@ -372,7 +372,7 @@ static int find_inode(const char __user
|
||||
if (error)
|
||||
return error;
|
||||
/* you can only watch an inode if you have read permissions on it */
|
||||
- error = inode_permission(path->dentry->d_inode, MAY_READ);
|
||||
+ error = path_permission(path, MAY_READ);
|
||||
if (error)
|
||||
path_put(path);
|
||||
return error;
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -226,7 +226,7 @@ int generic_permission(struct inode *ino
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
-int inode_permission(struct inode *inode, int mask)
|
||||
+static int __inode_permission(struct inode *inode, int mask)
|
||||
{
|
||||
int retval;
|
||||
|
||||
@@ -256,7 +256,12 @@ int inode_permission(struct inode *inode
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
- retval = devcgroup_inode_permission(inode, mask);
|
||||
+ return devcgroup_inode_permission(inode, mask);
|
||||
+}
|
||||
+
|
||||
+int inode_permission(struct inode *inode, int mask)
|
||||
+{
|
||||
+ int retval = __inode_permission(inode, mask);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
@@ -264,6 +269,15 @@ int inode_permission(struct inode *inode
|
||||
mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND));
|
||||
}
|
||||
|
||||
+int path_permission(struct path *path, int mask)
|
||||
+{
|
||||
+ int retval = __inode_permission(path->dentry->d_inode, mask);
|
||||
+ if (retval)
|
||||
+ return retval;
|
||||
+ return security_path_permission(path,
|
||||
+ mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND));
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* vfs_permission - check for access rights to a given path
|
||||
* @nd: lookup result that describes the path
|
||||
@@ -276,7 +290,7 @@ int inode_permission(struct inode *inode
|
||||
*/
|
||||
int vfs_permission(struct nameidata *nd, int mask)
|
||||
{
|
||||
- return inode_permission(nd->path.dentry->d_inode, mask);
|
||||
+ return path_permission(&nd->path, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -293,7 +307,7 @@ int vfs_permission(struct nameidata *nd,
|
||||
*/
|
||||
int file_permission(struct file *file, int mask)
|
||||
{
|
||||
- return inode_permission(file->f_path.dentry->d_inode, mask);
|
||||
+ return path_permission(&file->f_path, mask);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -434,8 +448,9 @@ static struct dentry * cached_lookup(str
|
||||
* short-cut DAC fails, then call permission() to do more
|
||||
* complete permission check.
|
||||
*/
|
||||
-static int exec_permission_lite(struct inode *inode)
|
||||
+static int exec_permission_lite(struct path *path)
|
||||
{
|
||||
+ struct inode *inode = path->dentry->d_inode;
|
||||
umode_t mode = inode->i_mode;
|
||||
|
||||
if (inode->i_op && inode->i_op->permission)
|
||||
@@ -460,7 +475,7 @@ static int exec_permission_lite(struct i
|
||||
|
||||
return -EACCES;
|
||||
ok:
|
||||
- return security_inode_permission(inode, MAY_EXEC);
|
||||
+ return security_path_permission(path, MAY_EXEC);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -857,7 +872,7 @@ static int __link_path_walk(const char *
|
||||
unsigned int c;
|
||||
|
||||
nd->flags |= LOOKUP_CONTINUE;
|
||||
- err = exec_permission_lite(inode);
|
||||
+ err = exec_permission_lite(&nd->path);
|
||||
if (err == -EAGAIN)
|
||||
err = vfs_permission(nd, MAY_EXEC);
|
||||
if (err)
|
||||
@@ -1216,7 +1231,7 @@ static struct dentry *lookup_hash(struct
|
||||
{
|
||||
int err;
|
||||
|
||||
- err = inode_permission(nd->path.dentry->d_inode, MAY_EXEC);
|
||||
+ err = path_permission(&nd->path, MAY_EXEC);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
return __lookup_hash(&nd->last, nd->path.dentry, nd);
|
||||
@@ -2862,6 +2877,7 @@ EXPORT_SYMBOL(path_lookup);
|
||||
EXPORT_SYMBOL(kern_path);
|
||||
EXPORT_SYMBOL(vfs_path_lookup);
|
||||
EXPORT_SYMBOL(inode_permission);
|
||||
+EXPORT_SYMBOL(path_permission);
|
||||
EXPORT_SYMBOL(vfs_permission);
|
||||
EXPORT_SYMBOL(file_permission);
|
||||
EXPORT_SYMBOL(unlock_rename);
|
||||
--- a/fs/open.c
|
||||
+++ b/fs/open.c
|
||||
@@ -250,7 +250,7 @@ static long do_sys_truncate(const char _
|
||||
if (error)
|
||||
goto dput_and_out;
|
||||
|
||||
- error = inode_permission(inode, MAY_WRITE);
|
||||
+ error = path_permission(&path, MAY_WRITE);
|
||||
if (error)
|
||||
goto mnt_drop_write_and_out;
|
||||
|
||||
@@ -474,7 +474,7 @@ asmlinkage long sys_faccessat(int dfd, c
|
||||
goto out_path_release;
|
||||
}
|
||||
|
||||
- res = inode_permission(inode, mode | MAY_ACCESS);
|
||||
+ res = path_permission(&path, mode | MAY_ACCESS);
|
||||
/* SuS v2 requires we report a read only fs too */
|
||||
if (res || !(mode & S_IWOTH) || special_file(inode->i_mode))
|
||||
goto out_path_release;
|
||||
@@ -517,7 +517,7 @@ asmlinkage long sys_chdir(const char __u
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
- error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
|
||||
+ error = path_permission(&path, MAY_EXEC | MAY_ACCESS);
|
||||
if (error)
|
||||
goto dput_and_out;
|
||||
|
||||
@@ -546,7 +546,7 @@ asmlinkage long sys_fchdir(unsigned int
|
||||
if (!S_ISDIR(inode->i_mode))
|
||||
goto out_putf;
|
||||
|
||||
- error = inode_permission(inode, MAY_EXEC | MAY_ACCESS);
|
||||
+ error = path_permission(&file->f_path, MAY_EXEC | MAY_ACCESS);
|
||||
if (!error)
|
||||
set_fs_pwd(current->fs, &file->f_path);
|
||||
out_putf:
|
||||
@@ -564,7 +564,7 @@ asmlinkage long sys_chroot(const char __
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
- error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
|
||||
+ error = path_permission(&path, MAY_EXEC | MAY_ACCESS);
|
||||
if (error)
|
||||
goto dput_and_out;
|
||||
|
||||
--- a/include/linux/fs.h
|
||||
+++ b/include/linux/fs.h
|
||||
@@ -1242,6 +1242,11 @@ int fiemap_fill_next_extent(struct fiema
|
||||
int fiemap_check_flags(struct fiemap_extent_info *fieinfo, u32 fs_flags);
|
||||
|
||||
/*
|
||||
+ * VFS path helper functions.
|
||||
+ */
|
||||
+extern int path_permission(struct path *, int);
|
||||
+
|
||||
+/*
|
||||
* File types
|
||||
*
|
||||
* NOTE! These match bits 12..15 of stat.st_mode
|
109
kernel-patches/2.6.28/add-security_path_permission
Normal file
109
kernel-patches/2.6.28/add-security_path_permission
Normal file
|
@ -0,0 +1,109 @@
|
|||
From: Jeff Mahoney <jeffm@suse.com>
|
||||
Subject: [PATCH] security: add ->path_permission
|
||||
|
||||
This patch adds a security_ops->path_permission hook that is identical to
|
||||
security_ops->inode_permission except that it is passed a struct path
|
||||
instead of a struct inode.
|
||||
|
||||
LSMs which don't implement it will have their ->inode_permission call
|
||||
used instead.
|
||||
|
||||
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
|
||||
include/linux/security.h | 21 +++++++++++++++++++++
|
||||
security/capability.c | 6 ++++++
|
||||
security/security.c | 9 +++++++++
|
||||
3 files changed, 36 insertions(+)
|
||||
|
||||
--- a/include/linux/security.h
|
||||
+++ b/include/linux/security.h
|
||||
@@ -592,6 +592,20 @@ static inline void security_free_mnt_opt
|
||||
* file_permission, and recheck access if anything has changed
|
||||
* since inode_permission.
|
||||
*
|
||||
+ * Security hook for path
|
||||
+ *
|
||||
+ * @path_permission:
|
||||
+ * Check permission before accessing a path. This hook is called by the
|
||||
+ * existing Linux permission function, so a security module can use it to
|
||||
+ * provide additional checking for existing Linux permission checks.
|
||||
+ * Notice that this hook is called when a file is opened (as well as many
|
||||
+ * other operations), whereas the file_security_ops permission hook is
|
||||
+ * called when the actual read/write operations are performed. This
|
||||
+ * hook is optional and if absent, inode_permission will be substituted.
|
||||
+ * @path contains the path structure to check.
|
||||
+ * @mask contains the permission mask.
|
||||
+ * Return 0 if permission is granted.
|
||||
+
|
||||
* Security hooks for task operations.
|
||||
*
|
||||
* @task_create:
|
||||
@@ -1434,6 +1448,7 @@ struct security_operations {
|
||||
struct fown_struct *fown, int sig);
|
||||
int (*file_receive) (struct file *file);
|
||||
int (*dentry_open) (struct file *file);
|
||||
+ int (*path_permission) (struct path *path, int mask);
|
||||
|
||||
int (*task_create) (unsigned long clone_flags);
|
||||
int (*task_alloc_security) (struct task_struct *p);
|
||||
@@ -1704,6 +1719,7 @@ int security_file_send_sigiotask(struct
|
||||
struct fown_struct *fown, int sig);
|
||||
int security_file_receive(struct file *file);
|
||||
int security_dentry_open(struct file *file);
|
||||
+int security_path_permission(struct path *path, int mask);
|
||||
int security_task_create(unsigned long clone_flags);
|
||||
int security_task_alloc(struct task_struct *p);
|
||||
void security_task_free(struct task_struct *p);
|
||||
@@ -2245,6 +2261,11 @@ static inline int security_dentry_open(s
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+static inline int security_path_permission(struct path *path, int mask)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
|
||||
static inline int security_task_create(unsigned long clone_flags)
|
||||
{
|
||||
--- a/security/capability.c
|
||||
+++ b/security/capability.c
|
||||
@@ -343,6 +343,11 @@ static int cap_dentry_open(struct file *
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int cap_path_permission(struct path *path, int mask)
|
||||
+{
|
||||
+ return security_inode_permission(path->dentry->d_inode, mask);
|
||||
+}
|
||||
+
|
||||
static int cap_task_create(unsigned long clone_flags)
|
||||
{
|
||||
return 0;
|
||||
@@ -897,6 +902,7 @@ void security_fixup_ops(struct security_
|
||||
set_to_cap_if_null(ops, file_send_sigiotask);
|
||||
set_to_cap_if_null(ops, file_receive);
|
||||
set_to_cap_if_null(ops, dentry_open);
|
||||
+ set_to_cap_if_null(ops, path_permission);
|
||||
set_to_cap_if_null(ops, task_create);
|
||||
set_to_cap_if_null(ops, task_alloc_security);
|
||||
set_to_cap_if_null(ops, task_free_security);
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -624,6 +624,15 @@ int security_dentry_open(struct file *fi
|
||||
return security_ops->dentry_open(file);
|
||||
}
|
||||
|
||||
+int security_path_permission(struct path *path, int mask)
|
||||
+{
|
||||
+ struct inode *inode = path->dentry->d_inode;
|
||||
+ if (unlikely(IS_PRIVATE(inode)))
|
||||
+ return 0;
|
||||
+
|
||||
+ return security_ops->path_permission(path, mask);
|
||||
+}
|
||||
+
|
||||
int security_task_create(unsigned long clone_flags)
|
||||
{
|
||||
return security_ops->task_create(clone_flags);
|
47
kernel-patches/2.6.28/apparmor-2.6.25.diff
Normal file
47
kernel-patches/2.6.28/apparmor-2.6.25.diff
Normal file
|
@ -0,0 +1,47 @@
|
|||
From: John Johansen <jjohansen@suse.de>
|
||||
Subject: AppArmor: Patch AppArmor for 2.6.25 kernel
|
||||
|
||||
Add 64 bit capabilities support to AppArmor.
|
||||
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
security/apparmor/module_interface.c | 22 ++++++++++++++++++----
|
||||
1 file changed, 18 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/security/apparmor/module_interface.c
|
||||
+++ b/security/apparmor/module_interface.c
|
||||
@@ -395,15 +395,29 @@ static struct aa_profile *aa_unpack_prof
|
||||
if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
|
||||
goto fail;
|
||||
|
||||
- if (!aa_is_u32(e, &(profile->capabilities), NULL))
|
||||
+ if (!aa_is_u32(e, &(profile->capabilities.cap[0]), NULL))
|
||||
goto fail;
|
||||
- if (!aa_is_u32(e, &(profile->audit_caps), NULL))
|
||||
+ if (!aa_is_u32(e, &(profile->audit_caps.cap[0]), NULL))
|
||||
goto fail;
|
||||
- if (!aa_is_u32(e, &(profile->quiet_caps), NULL))
|
||||
+ if (!aa_is_u32(e, &(profile->quiet_caps.cap[0]), NULL))
|
||||
goto fail;
|
||||
- if (!aa_is_u32(e, &(profile->set_caps), NULL))
|
||||
+ if (!aa_is_u32(e, &(profile->set_caps.cap[0]), NULL))
|
||||
goto fail;
|
||||
|
||||
+ if (aa_is_nameX(e, AA_STRUCT, "caps64")) {
|
||||
+ /* optional upper half of 64 bit caps */
|
||||
+ if (!aa_is_u32(e, &(profile->capabilities.cap[1]), NULL))
|
||||
+ goto fail;
|
||||
+ if (!aa_is_u32(e, &(profile->audit_caps.cap[1]), NULL))
|
||||
+ goto fail;
|
||||
+ if (!aa_is_u32(e, &(profile->quiet_caps.cap[1]), NULL))
|
||||
+ goto fail;
|
||||
+ if (!aa_is_u32(e, &(profile->set_caps.cap[1]), NULL))
|
||||
+ goto fail;
|
||||
+ if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
if (!aa_unpack_rlimits(e, profile))
|
||||
goto fail;
|
||||
|
72
kernel-patches/2.6.28/apparmor-audit.diff
Normal file
72
kernel-patches/2.6.28/apparmor-audit.diff
Normal file
|
@ -0,0 +1,72 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Export audit subsystem for use by modules
|
||||
|
||||
Update kenel audit range comments to show AppArmor's registered range of
|
||||
1500-1599. This range used to be reserved for LSPP but LSPP uses the
|
||||
SE Linux range and the range was given to AppArmor.
|
||||
Adds necessary export symbols for audit subsystem routines.
|
||||
Changes audit_log_vformat to be externally visible (analagous to vprintf)
|
||||
Patch is not in mainline -- pending AppArmor code submission to lkml
|
||||
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
include/linux/audit.h | 12 +++++++++++-
|
||||
kernel/audit.c | 6 ++++--
|
||||
2 files changed, 15 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/include/linux/audit.h
|
||||
+++ b/include/linux/audit.h
|
||||
@@ -33,7 +33,7 @@
|
||||
* 1200 - 1299 messages internal to the audit daemon
|
||||
* 1300 - 1399 audit event messages
|
||||
* 1400 - 1499 SE Linux use
|
||||
- * 1500 - 1599 kernel LSPP events
|
||||
+ * 1500 - 1599 AppArmor use
|
||||
* 1600 - 1699 kernel crypto events
|
||||
* 1700 - 1799 kernel anomaly records
|
||||
* 1800 - 1999 future kernel use (maybe integrity labels and related events)
|
||||
@@ -119,6 +119,13 @@
|
||||
#define AUDIT_MAC_UNLBL_STCADD 1416 /* NetLabel: add a static label */
|
||||
#define AUDIT_MAC_UNLBL_STCDEL 1417 /* NetLabel: del a static label */
|
||||
|
||||
+#define AUDIT_APPARMOR_AUDIT 1501 /* AppArmor audited grants */
|
||||
+#define AUDIT_APPARMOR_ALLOWED 1502 /* Allowed Access for learning */
|
||||
+#define AUDIT_APPARMOR_DENIED 1503
|
||||
+#define AUDIT_APPARMOR_HINT 1504 /* Process Tracking information */
|
||||
+#define AUDIT_APPARMOR_STATUS 1505 /* Changes in config */
|
||||
+#define AUDIT_APPARMOR_ERROR 1506 /* Internal AppArmor Errors */
|
||||
+
|
||||
#define AUDIT_FIRST_KERN_ANOM_MSG 1700
|
||||
#define AUDIT_LAST_KERN_ANOM_MSG 1799
|
||||
#define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */
|
||||
@@ -547,6 +554,9 @@ extern void audit_log(struct audit_
|
||||
__attribute__((format(printf,4,5)));
|
||||
|
||||
extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type);
|
||||
+extern void audit_log_vformat(struct audit_buffer *ab,
|
||||
+ const char *fmt, va_list args)
|
||||
+ __attribute__((format(printf,2,0)));
|
||||
extern void audit_log_format(struct audit_buffer *ab,
|
||||
const char *fmt, ...)
|
||||
__attribute__((format(printf,2,3)));
|
||||
--- a/kernel/audit.c
|
||||
+++ b/kernel/audit.c
|
||||
@@ -1243,8 +1243,7 @@ static inline int audit_expand(struct au
|
||||
* will be called a second time. Currently, we assume that a printk
|
||||
* can't format message larger than 1024 bytes, so we don't either.
|
||||
*/
|
||||
-static void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
|
||||
- va_list args)
|
||||
+void audit_log_vformat(struct audit_buffer *ab, const char *fmt, va_list args)
|
||||
{
|
||||
int len, avail;
|
||||
struct sk_buff *skb;
|
||||
@@ -1518,3 +1517,6 @@ EXPORT_SYMBOL(audit_log_start);
|
||||
EXPORT_SYMBOL(audit_log_end);
|
||||
EXPORT_SYMBOL(audit_log_format);
|
||||
EXPORT_SYMBOL(audit_log);
|
||||
+EXPORT_SYMBOL_GPL(audit_log_vformat);
|
||||
+EXPORT_SYMBOL_GPL(audit_log_untrustedstring);
|
||||
+EXPORT_SYMBOL_GPL(audit_log_d_path);
|
31
kernel-patches/2.6.28/apparmor-intree.diff
Normal file
31
kernel-patches/2.6.28/apparmor-intree.diff
Normal file
|
@ -0,0 +1,31 @@
|
|||
From: John Johansen <jjohansen@suse.de>
|
||||
Subject: Add AppArmor LSM to security/Makefile
|
||||
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
|
||||
---
|
||||
security/Kconfig | 1 +
|
||||
security/Makefile | 3 ++-
|
||||
2 files changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/security/Kconfig
|
||||
+++ b/security/Kconfig
|
||||
@@ -134,6 +134,7 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
|
||||
|
||||
source security/selinux/Kconfig
|
||||
source security/smack/Kconfig
|
||||
+source security/apparmor/Kconfig
|
||||
|
||||
endmenu
|
||||
|
||||
--- a/security/Makefile
|
||||
+++ b/security/Makefile
|
||||
@@ -15,5 +15,6 @@ obj-$(CONFIG_SECURITYFS) += inode.o
|
||||
# Must precede capability.o in order to stack properly.
|
||||
obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
|
||||
obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
|
||||
-obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o
|
||||
+obj-$(CONFIG_SECURITY_APPARMOR) += commoncap.o apparmor/
|
||||
+ obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o
|
||||
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
|
910
kernel-patches/2.6.28/apparmor-lsm.diff
Normal file
910
kernel-patches/2.6.28/apparmor-lsm.diff
Normal file
|
@ -0,0 +1,910 @@
|
|||
From: John Johansen <jjohansen@suse.de>
|
||||
Subject: AppArmor: Module and LSM hooks
|
||||
|
||||
Module parameters, LSM hooks, initialization and teardown.
|
||||
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
|
||||
---
|
||||
security/apparmor/lsm.c | 895 ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 895 insertions(+)
|
||||
|
||||
--- /dev/null
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -0,0 +1,895 @@
|
||||
+/*
|
||||
+ * Copyright (C) 1998-2007 Novell/SUSE
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation, version 2 of the
|
||||
+ * License.
|
||||
+ *
|
||||
+ * AppArmor LSM interface
|
||||
+ */
|
||||
+
|
||||
+#include <linux/security.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/mm.h>
|
||||
+#include <linux/mman.h>
|
||||
+#include <linux/mount.h>
|
||||
+#include <linux/namei.h>
|
||||
+#include <linux/ctype.h>
|
||||
+#include <linux/sysctl.h>
|
||||
+#include <linux/audit.h>
|
||||
+
|
||||
+#include "apparmor.h"
|
||||
+#include "inline.h"
|
||||
+
|
||||
+/* Flag indicating whether initialization completed */
|
||||
+int apparmor_initialized = 0;
|
||||
+
|
||||
+static int param_set_aabool(const char *val, struct kernel_param *kp);
|
||||
+static int param_get_aabool(char *buffer, struct kernel_param *kp);
|
||||
+#define param_check_aabool(name, p) __param_check(name, p, int)
|
||||
+
|
||||
+static int param_set_aauint(const char *val, struct kernel_param *kp);
|
||||
+static int param_get_aauint(char *buffer, struct kernel_param *kp);
|
||||
+#define param_check_aauint(name, p) __param_check(name, p, int)
|
||||
+
|
||||
+/* Flag values, also controllable via /sys/module/apparmor/parameters
|
||||
+ * We define special types as we want to do additional mediation.
|
||||
+ *
|
||||
+ * Complain mode -- in complain mode access failures result in auditing only
|
||||
+ * and task is allowed access. audit events are processed by userspace to
|
||||
+ * generate policy. Default is 'enforce' (0).
|
||||
+ * Value is also togglable per profile and referenced when global value is
|
||||
+ * enforce.
|
||||
+ */
|
||||
+int apparmor_complain = 0;
|
||||
+module_param_named(complain, apparmor_complain, aabool, S_IRUSR | S_IWUSR);
|
||||
+MODULE_PARM_DESC(apparmor_complain, "Toggle AppArmor complain mode");
|
||||
+
|
||||
+/* Debug mode */
|
||||
+int apparmor_debug = 0;
|
||||
+module_param_named(debug, apparmor_debug, aabool, S_IRUSR | S_IWUSR);
|
||||
+MODULE_PARM_DESC(apparmor_debug, "Toggle AppArmor debug mode");
|
||||
+
|
||||
+/* Audit mode */
|
||||
+int apparmor_audit = 0;
|
||||
+module_param_named(audit, apparmor_audit, aabool, S_IRUSR | S_IWUSR);
|
||||
+MODULE_PARM_DESC(apparmor_audit, "Toggle AppArmor audit mode");
|
||||
+
|
||||
+/* Syscall logging mode */
|
||||
+int apparmor_logsyscall = 0;
|
||||
+module_param_named(logsyscall, apparmor_logsyscall, aabool, S_IRUSR | S_IWUSR);
|
||||
+MODULE_PARM_DESC(apparmor_logsyscall, "Toggle AppArmor logsyscall mode");
|
||||
+
|
||||
+/* Maximum pathname length before accesses will start getting rejected */
|
||||
+unsigned int apparmor_path_max = 2 * PATH_MAX;
|
||||
+module_param_named(path_max, apparmor_path_max, aauint, S_IRUSR | S_IWUSR);
|
||||
+MODULE_PARM_DESC(apparmor_path_max, "Maximum pathname length allowed");
|
||||
+
|
||||
+/* Boot time disable flag */
|
||||
+#ifdef CONFIG_SECURITY_APPARMOR_DISABLE
|
||||
+#define AA_ENABLED_PERMS 0600
|
||||
+#else
|
||||
+#define AA_ENABLED_PERMS 0400
|
||||
+#endif
|
||||
+static int param_set_aa_enabled(const char *val, struct kernel_param *kp);
|
||||
+unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
|
||||
+module_param_call(enabled, param_set_aa_enabled, param_get_aauint,
|
||||
+ &apparmor_enabled, AA_ENABLED_PERMS);
|
||||
+MODULE_PARM_DESC(apparmor_enabled, "Enable/Disable Apparmor on boot");
|
||||
+
|
||||
+static int __init apparmor_enabled_setup(char *str)
|
||||
+{
|
||||
+ apparmor_enabled = simple_strtol(str, NULL, 0);
|
||||
+ return 1;
|
||||
+}
|
||||
+__setup("apparmor=", apparmor_enabled_setup);
|
||||
+
|
||||
+static int param_set_aabool(const char *val, struct kernel_param *kp)
|
||||
+{
|
||||
+ if (aa_task_context(current))
|
||||
+ return -EPERM;
|
||||
+ return param_set_bool(val, kp);
|
||||
+}
|
||||
+
|
||||
+static int param_get_aabool(char *buffer, struct kernel_param *kp)
|
||||
+{
|
||||
+ if (aa_task_context(current))
|
||||
+ return -EPERM;
|
||||
+ return param_get_bool(buffer, kp);
|
||||
+}
|
||||
+
|
||||
+static int param_set_aauint(const char *val, struct kernel_param *kp)
|
||||
+{
|
||||
+ if (aa_task_context(current))
|
||||
+ return -EPERM;
|
||||
+ return param_set_uint(val, kp);
|
||||
+}
|
||||
+
|
||||
+static int param_get_aauint(char *buffer, struct kernel_param *kp)
|
||||
+{
|
||||
+ if (aa_task_context(current))
|
||||
+ return -EPERM;
|
||||
+ return param_get_uint(buffer, kp);
|
||||
+}
|
||||
+
|
||||
+/* allow run time disabling of apparmor */
|
||||
+static int param_set_aa_enabled(const char *val, struct kernel_param *kp)
|
||||
+{
|
||||
+ char *endp;
|
||||
+ unsigned long l;
|
||||
+
|
||||
+ if (!apparmor_initialized) {
|
||||
+ apparmor_enabled = 0;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (aa_task_context(current))
|
||||
+ return -EPERM;
|
||||
+
|
||||
+ if (!apparmor_enabled)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!val)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ l = simple_strtoul(val, &endp, 0);
|
||||
+ if (endp == val || l != 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ apparmor_enabled = 0;
|
||||
+ apparmor_disable();
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int aa_reject_syscall(struct task_struct *task, gfp_t flags,
|
||||
+ const char *name)
|
||||
+{
|
||||
+ struct aa_profile *profile = aa_get_profile(task);
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (profile) {
|
||||
+ error = aa_audit_syscallreject(profile, flags, name);
|
||||
+ aa_put_profile(profile);
|
||||
+ }
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_ptrace(struct task_struct *parent,
|
||||
+ struct task_struct *child, unsigned int mode)
|
||||
+{
|
||||
+ struct aa_task_context *cxt;
|
||||
+ int error = 0;
|
||||
+
|
||||
+ /*
|
||||
+ * parent can ptrace child when
|
||||
+ * - parent is unconfined
|
||||
+ * - parent & child are in the same namespace &&
|
||||
+ * - parent is in complain mode
|
||||
+ * - parent and child are confined by the same profile
|
||||
+ * - parent profile has CAP_SYS_PTRACE
|
||||
+ */
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ cxt = aa_task_context(parent);
|
||||
+ if (cxt) {
|
||||
+ if (parent->nsproxy != child->nsproxy) {
|
||||
+ struct aa_audit sa;
|
||||
+ memset(&sa, 0, sizeof(sa));
|
||||
+ sa.operation = "ptrace";
|
||||
+ sa.gfp_mask = GFP_ATOMIC;
|
||||
+ sa.parent = parent->pid;
|
||||
+ sa.task = child->pid;
|
||||
+ sa.info = "different namespaces";
|
||||
+ aa_audit_reject(cxt->profile, &sa);
|
||||
+ error = -EPERM;
|
||||
+ } else {
|
||||
+ struct aa_task_context *child_cxt =
|
||||
+ aa_task_context(child);
|
||||
+
|
||||
+ error = aa_may_ptrace(cxt, child_cxt ?
|
||||
+ child_cxt->profile : NULL);
|
||||
+ if (error && PROFILE_COMPLAIN(cxt->profile)) {
|
||||
+ struct aa_audit sa;
|
||||
+ memset(&sa, 0, sizeof(sa));
|
||||
+ sa.operation = "ptrace";
|
||||
+ sa.gfp_mask = GFP_ATOMIC;
|
||||
+ sa.parent = parent->pid;
|
||||
+ sa.task = child->pid;
|
||||
+ aa_audit_hint(cxt->profile, &sa);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_capable(struct task_struct *task, int cap)
|
||||
+{
|
||||
+ int error;
|
||||
+ struct aa_task_context *cxt;
|
||||
+
|
||||
+ /* cap_capable returns 0 on success, else -EPERM */
|
||||
+ error = cap_capable(task, cap);
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ cxt = aa_task_context(task);
|
||||
+ if (cxt && (!error || cap_raised(cxt->profile->set_caps, cap)))
|
||||
+ error = aa_capability(cxt, cap);
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_sysctl(struct ctl_table *table, int op)
|
||||
+{
|
||||
+ struct aa_profile *profile = aa_get_profile(current);
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (profile) {
|
||||
+ char *buffer, *name;
|
||||
+ int mask;
|
||||
+
|
||||
+ mask = 0;
|
||||
+ if (op & 4)
|
||||
+ mask |= MAY_READ;
|
||||
+ if (op & 2)
|
||||
+ mask |= MAY_WRITE;
|
||||
+
|
||||
+ error = -ENOMEM;
|
||||
+ buffer = (char*)__get_free_page(GFP_KERNEL);
|
||||
+ if (!buffer)
|
||||
+ goto out;
|
||||
+ name = sysctl_pathname(table, buffer, PAGE_SIZE);
|
||||
+ if (name && name - buffer >= 5) {
|
||||
+ name -= 5;
|
||||
+ memcpy(name, "/proc", 5);
|
||||
+ error = aa_perm_path(profile, "sysctl", name, mask, 0);
|
||||
+ }
|
||||
+ free_page((unsigned long)buffer);
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ aa_put_profile(profile);
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_bprm_set_security(struct linux_binprm *bprm)
|
||||
+{
|
||||
+ /* handle capability bits with setuid, etc */
|
||||
+ cap_bprm_set_security(bprm);
|
||||
+ /* already set based on script name */
|
||||
+ if (bprm->sh_bang)
|
||||
+ return 0;
|
||||
+ return aa_register(bprm);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_bprm_secureexec(struct linux_binprm *bprm)
|
||||
+{
|
||||
+ int ret = cap_bprm_secureexec(bprm);
|
||||
+
|
||||
+ if (!ret && (unsigned long)bprm->security & AA_SECURE_EXEC_NEEDED) {
|
||||
+ AA_DEBUG("%s: secureexec required for %s\n",
|
||||
+ __FUNCTION__, bprm->filename);
|
||||
+ ret = 1;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_sb_mount(char *dev_name, struct path *path, char *type,
|
||||
+ unsigned long flags, void *data)
|
||||
+{
|
||||
+ return aa_reject_syscall(current, GFP_KERNEL, "mount");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_umount(struct vfsmount *mnt, int flags)
|
||||
+{
|
||||
+ return aa_reject_syscall(current, GFP_KERNEL, "umount");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_mkdir(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, int mask)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (!mnt || !mediated_filesystem(dir))
|
||||
+ goto out;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+
|
||||
+ if (profile)
|
||||
+ error = aa_perm_dir(profile, "inode_mkdir", dentry, mnt,
|
||||
+ MAY_WRITE);
|
||||
+
|
||||
+ aa_put_profile(profile);
|
||||
+
|
||||
+out:
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_rmdir(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (!mnt || !mediated_filesystem(dir))
|
||||
+ goto out;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+
|
||||
+ if (profile)
|
||||
+ error = aa_perm_dir(profile, "inode_rmdir", dentry, mnt,
|
||||
+ MAY_WRITE);
|
||||
+
|
||||
+ aa_put_profile(profile);
|
||||
+
|
||||
+out:
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int aa_permission(const char *operation, struct inode *inode,
|
||||
+ struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ int mask, int check)
|
||||
+{
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (mnt && mediated_filesystem(inode)) {
|
||||
+ struct aa_profile *profile;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+ if (profile)
|
||||
+ error = aa_perm(profile, operation, dentry, mnt, mask,
|
||||
+ check);
|
||||
+ aa_put_profile(profile);
|
||||
+ }
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static inline int aa_mask_permissions(int mask)
|
||||
+{
|
||||
+ if (mask & MAY_APPEND)
|
||||
+ mask &= (MAY_READ | MAY_APPEND | MAY_EXEC);
|
||||
+ else
|
||||
+ mask &= (MAY_READ | MAY_WRITE | MAY_EXEC);
|
||||
+ return mask;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_create(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, int mask)
|
||||
+{
|
||||
+ return aa_permission("inode_create", dir, dentry, mnt, MAY_APPEND, 0);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_link(struct dentry *old_dentry,
|
||||
+ struct vfsmount *old_mnt, struct inode *dir,
|
||||
+ struct dentry *new_dentry,
|
||||
+ struct vfsmount *new_mnt)
|
||||
+{
|
||||
+ int error = 0;
|
||||
+ struct aa_profile *profile;
|
||||
+
|
||||
+ if (!old_mnt || !new_mnt || !mediated_filesystem(dir))
|
||||
+ goto out;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+
|
||||
+ if (profile)
|
||||
+ error = aa_link(profile, new_dentry, new_mnt,
|
||||
+ old_dentry, old_mnt);
|
||||
+
|
||||
+ aa_put_profile(profile);
|
||||
+
|
||||
+out:
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_unlink(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt)
|
||||
+{
|
||||
+ int check = 0;
|
||||
+
|
||||
+ if (S_ISDIR(dentry->d_inode->i_mode))
|
||||
+ check |= AA_CHECK_DIR;
|
||||
+ return aa_permission("inode_unlink", dir, dentry, mnt, MAY_WRITE,
|
||||
+ check);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_symlink(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, const char *old_name)
|
||||
+{
|
||||
+ return aa_permission("inode_symlink", dir, dentry, mnt, MAY_WRITE, 0);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_mknod(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, int mode, dev_t dev)
|
||||
+{
|
||||
+ return aa_permission("inode_mknod", dir, dentry, mnt, MAY_WRITE, 0);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_rename(struct inode *old_dir,
|
||||
+ struct dentry *old_dentry,
|
||||
+ struct vfsmount *old_mnt,
|
||||
+ struct inode *new_dir,
|
||||
+ struct dentry *new_dentry,
|
||||
+ struct vfsmount *new_mnt)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if ((!old_mnt && !new_mnt) || !mediated_filesystem(old_dir))
|
||||
+ goto out;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+
|
||||
+ if (profile) {
|
||||
+ struct inode *inode = old_dentry->d_inode;
|
||||
+ int check = 0;
|
||||
+
|
||||
+ if (inode && S_ISDIR(inode->i_mode))
|
||||
+ check |= AA_CHECK_DIR;
|
||||
+ if (old_mnt)
|
||||
+ error = aa_perm(profile, "inode_rename", old_dentry,
|
||||
+ old_mnt, MAY_READ | MAY_WRITE, check);
|
||||
+
|
||||
+ if (!error && new_mnt) {
|
||||
+ error = aa_perm(profile, "inode_rename", new_dentry,
|
||||
+ new_mnt, MAY_WRITE, check);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ aa_put_profile(profile);
|
||||
+
|
||||
+out:
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_permission(struct inode *inode, int mask,
|
||||
+ struct nameidata *nd)
|
||||
+{
|
||||
+ int check = 0;
|
||||
+
|
||||
+ if (!nd || nd->flags & (LOOKUP_PARENT | LOOKUP_CONTINUE))
|
||||
+ return 0;
|
||||
+ mask = aa_mask_permissions(mask);
|
||||
+ if (S_ISDIR(inode->i_mode)) {
|
||||
+ check |= AA_CHECK_DIR;
|
||||
+ /* allow traverse accesses to directories */
|
||||
+ mask &= ~MAY_EXEC;
|
||||
+ }
|
||||
+ return aa_permission("inode_permission", inode, nd->dentry, nd->mnt,
|
||||
+ mask, check);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ struct iattr *iattr)
|
||||
+{
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (!mnt)
|
||||
+ goto out;
|
||||
+
|
||||
+ if (mediated_filesystem(dentry->d_inode)) {
|
||||
+ struct aa_profile *profile;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+ /*
|
||||
+ * Mediate any attempt to change attributes of a file
|
||||
+ * (chmod, chown, chgrp, etc)
|
||||
+ */
|
||||
+ if (profile)
|
||||
+ error = aa_attr(profile, dentry, mnt, iattr);
|
||||
+
|
||||
+ aa_put_profile(profile);
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int aa_xattr_permission(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *operation, int mask,
|
||||
+ struct file *file)
|
||||
+{
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (mnt && mediated_filesystem(dentry->d_inode)) {
|
||||
+ struct aa_profile *profile = aa_get_profile(current);
|
||||
+ int check = file ? AA_CHECK_FD : 0;
|
||||
+
|
||||
+ if (profile)
|
||||
+ error = aa_perm_xattr(profile, operation, dentry, mnt,
|
||||
+ mask, check);
|
||||
+ aa_put_profile(profile);
|
||||
+ }
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name, const void *value,
|
||||
+ size_t size, int flags, struct file *file)
|
||||
+{
|
||||
+ int error = cap_inode_setxattr(dentry, mnt, name, value, size, flags,
|
||||
+ file);
|
||||
+
|
||||
+ if (!error)
|
||||
+ error = aa_xattr_permission(dentry, mnt, "xattr set",
|
||||
+ MAY_WRITE, file);
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name, struct file *file)
|
||||
+{
|
||||
+ return aa_xattr_permission(dentry, mnt, "xattr get", MAY_READ, file);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ struct file *file)
|
||||
+{
|
||||
+ return aa_xattr_permission(dentry, mnt, "xattr list", MAY_READ, file);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_removexattr(struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, const char *name,
|
||||
+ struct file *file)
|
||||
+{
|
||||
+ return aa_xattr_permission(dentry, mnt, "xattr remove", MAY_WRITE,
|
||||
+ file);
|
||||
+}
|
||||
+
|
||||
+static int aa_file_permission(const char *op, struct file *file, int mask)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+ struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (!file_profile)
|
||||
+ goto out;
|
||||
+
|
||||
+ /*
|
||||
+ * If this file was opened under a different profile, we
|
||||
+ * revalidate the access against the current profile.
|
||||
+ */
|
||||
+ profile = aa_get_profile(current);
|
||||
+ if (profile && (file_profile != profile || mask & AA_MAY_LOCK)) {
|
||||
+ struct dentry *dentry = file->f_dentry;
|
||||
+ struct vfsmount *mnt = file->f_vfsmnt;
|
||||
+ struct inode *inode = dentry->d_inode;
|
||||
+ int check = AA_CHECK_FD;
|
||||
+
|
||||
+ /*
|
||||
+ * FIXME: We should remember which profiles we revalidated
|
||||
+ * against.
|
||||
+ */
|
||||
+ if (S_ISDIR(inode->i_mode))
|
||||
+ check |= AA_CHECK_DIR;
|
||||
+ error = aa_permission(op, inode, dentry, mnt, mask, check);
|
||||
+ }
|
||||
+ aa_put_profile(profile);
|
||||
+
|
||||
+out:
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_file_permission(struct file *file, int mask)
|
||||
+{
|
||||
+ return aa_file_permission("file_permission", file,
|
||||
+ aa_mask_permissions(mask));
|
||||
+}
|
||||
+
|
||||
+static inline int apparmor_file_lock (struct file *file, unsigned int cmd)
|
||||
+{
|
||||
+ int mask = AA_MAY_LOCK;
|
||||
+ if (cmd == F_WRLCK)
|
||||
+ mask |= MAY_WRITE;
|
||||
+ return aa_file_permission("file_lock", file, mask);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_file_alloc_security(struct file *file)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+ if (profile)
|
||||
+ file->f_security = profile;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void apparmor_file_free_security(struct file *file)
|
||||
+{
|
||||
+ struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
|
||||
+
|
||||
+ aa_put_profile(file_profile);
|
||||
+}
|
||||
+
|
||||
+static inline int aa_mmap(struct file *file, const char *operation,
|
||||
+ unsigned long prot, unsigned long flags)
|
||||
+{
|
||||
+ struct dentry *dentry;
|
||||
+ int mask = 0;
|
||||
+
|
||||
+ if (!file || !file->f_security)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (prot & PROT_READ)
|
||||
+ mask |= MAY_READ;
|
||||
+ /* Private mappings don't require write perms since they don't
|
||||
+ * write back to the files */
|
||||
+ if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE))
|
||||
+ mask |= MAY_WRITE;
|
||||
+ if (prot & PROT_EXEC)
|
||||
+ mask |= AA_EXEC_MMAP;
|
||||
+
|
||||
+ dentry = file->f_dentry;
|
||||
+ return aa_permission(operation, dentry->d_inode, dentry,
|
||||
+ file->f_vfsmnt, mask, AA_CHECK_FD);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
|
||||
+ unsigned long prot, unsigned long flags,
|
||||
+ unsigned long addr, unsigned long addr_only)
|
||||
+{
|
||||
+ if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO)) {
|
||||
+ struct aa_profile *profile = aa_get_profile(current);
|
||||
+ if (profile)
|
||||
+ /* future control check here */
|
||||
+ return -EACCES;
|
||||
+ else
|
||||
+ return -EACCES;
|
||||
+ aa_put_profile(profile);
|
||||
+ }
|
||||
+
|
||||
+ return aa_mmap(file, "file_mmap", prot, flags);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_file_mprotect(struct vm_area_struct *vma,
|
||||
+ unsigned long reqprot, unsigned long prot)
|
||||
+{
|
||||
+ return aa_mmap(vma->vm_file, "file_mprotect", prot,
|
||||
+ !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_task_alloc_security(struct task_struct *task)
|
||||
+{
|
||||
+ return aa_clone(task);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Called from IRQ context from RCU callback.
|
||||
+ */
|
||||
+static void apparmor_task_free_security(struct task_struct *task)
|
||||
+{
|
||||
+ aa_release(task);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_getprocattr(struct task_struct *task, char *name,
|
||||
+ char **value)
|
||||
+{
|
||||
+ unsigned len;
|
||||
+ int error;
|
||||
+ struct aa_profile *profile;
|
||||
+
|
||||
+ /* AppArmor only supports the "current" process attribute */
|
||||
+ if (strcmp(name, "current") != 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* must be task querying itself or admin */
|
||||
+ if (current != task && !capable(CAP_SYS_ADMIN))
|
||||
+ return -EPERM;
|
||||
+
|
||||
+ profile = aa_get_profile(task);
|
||||
+ error = aa_getprocattr(profile, value, &len);
|
||||
+ aa_put_profile(profile);
|
||||
+ if (!error)
|
||||
+ error = len;
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_setprocattr(struct task_struct *task, char *name,
|
||||
+ void *value, size_t size)
|
||||
+{
|
||||
+ char *command, *args;
|
||||
+ int error;
|
||||
+
|
||||
+ if (strcmp(name, "current") != 0 || size == 0 || size >= PAGE_SIZE)
|
||||
+ return -EINVAL;
|
||||
+ args = value;
|
||||
+ args[size] = '\0';
|
||||
+ args = strstrip(args);
|
||||
+ command = strsep(&args, " ");
|
||||
+ if (!args)
|
||||
+ return -EINVAL;
|
||||
+ while (isspace(*args))
|
||||
+ args++;
|
||||
+ if (!*args)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (strcmp(command, "changehat") == 0) {
|
||||
+ if (current != task)
|
||||
+ return -EACCES;
|
||||
+ error = aa_setprocattr_changehat(args);
|
||||
+ } else if (strcmp(command, "changeprofile") == 0) {
|
||||
+ if (current != task)
|
||||
+ return -EACCES;
|
||||
+ error = aa_setprocattr_changeprofile(args);
|
||||
+ } else if (strcmp(command, "setprofile") == 0) {
|
||||
+ struct aa_profile *profile;
|
||||
+
|
||||
+ /* Only an unconfined process with admin capabilities
|
||||
+ * may change the profile of another task.
|
||||
+ */
|
||||
+
|
||||
+ if (!capable(CAP_SYS_ADMIN))
|
||||
+ return -EACCES;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+ if (profile) {
|
||||
+ struct aa_audit sa;
|
||||
+ memset(&sa, 0, sizeof(sa));
|
||||
+ sa.operation = "profile_set";
|
||||
+ sa.gfp_mask = GFP_KERNEL;
|
||||
+ sa.task = task->pid;
|
||||
+ sa.info = "from confined process";
|
||||
+ aa_audit_reject(profile, &sa);
|
||||
+ aa_put_profile(profile);
|
||||
+ return -EACCES;
|
||||
+ }
|
||||
+ error = aa_setprocattr_setprofile(task, args);
|
||||
+ } else {
|
||||
+ struct aa_audit sa;
|
||||
+ memset(&sa, 0, sizeof(sa));
|
||||
+ sa.operation = "setprocattr";
|
||||
+ sa.gfp_mask = GFP_KERNEL;
|
||||
+ sa.info = "invalid command";
|
||||
+ sa.name = command;
|
||||
+ sa.task = task->pid;
|
||||
+ aa_audit_reject(NULL, &sa);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (!error)
|
||||
+ error = size;
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+struct security_operations apparmor_ops = {
|
||||
+ .ptrace = apparmor_ptrace,
|
||||
+ .capget = cap_capget,
|
||||
+ .capset_check = cap_capset_check,
|
||||
+ .capset_set = cap_capset_set,
|
||||
+ .sysctl = apparmor_sysctl,
|
||||
+ .capable = apparmor_capable,
|
||||
+ .syslog = cap_syslog,
|
||||
+
|
||||
+ .netlink_send = cap_netlink_send,
|
||||
+ .netlink_recv = cap_netlink_recv,
|
||||
+
|
||||
+ .bprm_apply_creds = cap_bprm_apply_creds,
|
||||
+ .bprm_set_security = apparmor_bprm_set_security,
|
||||
+ .bprm_secureexec = apparmor_bprm_secureexec,
|
||||
+
|
||||
+ .sb_mount = apparmor_sb_mount,
|
||||
+ .sb_umount = apparmor_umount,
|
||||
+
|
||||
+ .inode_mkdir = apparmor_inode_mkdir,
|
||||
+ .inode_rmdir = apparmor_inode_rmdir,
|
||||
+ .inode_create = apparmor_inode_create,
|
||||
+ .inode_link = apparmor_inode_link,
|
||||
+ .inode_unlink = apparmor_inode_unlink,
|
||||
+ .inode_symlink = apparmor_inode_symlink,
|
||||
+ .inode_mknod = apparmor_inode_mknod,
|
||||
+ .inode_rename = apparmor_inode_rename,
|
||||
+ .inode_permission = apparmor_inode_permission,
|
||||
+ .inode_setattr = apparmor_inode_setattr,
|
||||
+ .inode_setxattr = apparmor_inode_setxattr,
|
||||
+ .inode_getxattr = apparmor_inode_getxattr,
|
||||
+ .inode_listxattr = apparmor_inode_listxattr,
|
||||
+ .inode_removexattr = apparmor_inode_removexattr,
|
||||
+ .file_permission = apparmor_file_permission,
|
||||
+ .file_alloc_security = apparmor_file_alloc_security,
|
||||
+ .file_free_security = apparmor_file_free_security,
|
||||
+ .file_mmap = apparmor_file_mmap,
|
||||
+ .file_mprotect = apparmor_file_mprotect,
|
||||
+ .file_lock = apparmor_file_lock,
|
||||
+
|
||||
+ .task_alloc_security = apparmor_task_alloc_security,
|
||||
+ .task_free_security = apparmor_task_free_security,
|
||||
+ .task_post_setuid = cap_task_post_setuid,
|
||||
+ .task_reparent_to_init = cap_task_reparent_to_init,
|
||||
+
|
||||
+ .getprocattr = apparmor_getprocattr,
|
||||
+ .setprocattr = apparmor_setprocattr,
|
||||
+};
|
||||
+
|
||||
+void info_message(const char *str)
|
||||
+{
|
||||
+ struct aa_audit sa;
|
||||
+ memset(&sa, 0, sizeof(sa));
|
||||
+ sa.gfp_mask = GFP_KERNEL;
|
||||
+ sa.info = str;
|
||||
+ printk(KERN_INFO "AppArmor: %s\n", str);
|
||||
+ if (audit_enabled)
|
||||
+ aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS);
|
||||
+}
|
||||
+
|
||||
+static int __init apparmor_init(void)
|
||||
+{
|
||||
+ int error;
|
||||
+
|
||||
+ if (!apparmor_enabled) {
|
||||
+ info_message("AppArmor disabled by boottime parameter\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if ((error = create_apparmorfs())) {
|
||||
+ AA_ERROR("Unable to activate AppArmor filesystem\n");
|
||||
+ goto createfs_out;
|
||||
+ }
|
||||
+
|
||||
+ if ((error = alloc_default_namespace())){
|
||||
+ AA_ERROR("Unable to allocate default profile namespace\n");
|
||||
+ goto alloc_out;
|
||||
+ }
|
||||
+
|
||||
+ if ((error = register_security(&apparmor_ops))) {
|
||||
+ AA_ERROR("Unable to register AppArmor\n");
|
||||
+ goto register_security_out;
|
||||
+ }
|
||||
+
|
||||
+ /* Report that AppArmor successfully initialized */
|
||||
+ apparmor_initialized = 1;
|
||||
+ if (apparmor_complain)
|
||||
+ info_message("AppArmor initialized: complainmode enabled");
|
||||
+ else
|
||||
+ info_message("AppArmor initialized");
|
||||
+
|
||||
+ return error;
|
||||
+
|
||||
+register_security_out:
|
||||
+ free_default_namespace();
|
||||
+
|
||||
+alloc_out:
|
||||
+ destroy_apparmorfs();
|
||||
+
|
||||
+createfs_out:
|
||||
+ return error;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+security_initcall(apparmor_init);
|
||||
+
|
||||
+void apparmor_disable(void)
|
||||
+{
|
||||
+ /* Remove and release all the profiles on the profile list. */
|
||||
+ mutex_lock(&aa_interface_lock);
|
||||
+ aa_profile_ns_list_release();
|
||||
+
|
||||
+ /* FIXME: cleanup profiles references on files */
|
||||
+ free_default_namespace();
|
||||
+
|
||||
+ /*
|
||||
+ * Delay for an rcu cycle to make sure that all active task
|
||||
+ * context readers have finished, and all profiles have been
|
||||
+ * freed by their rcu callbacks.
|
||||
+ */
|
||||
+ synchronize_rcu();
|
||||
+
|
||||
+ destroy_apparmorfs();
|
||||
+ mutex_unlock(&aa_interface_lock);
|
||||
+
|
||||
+ apparmor_initialized = 0;
|
||||
+
|
||||
+ info_message("AppArmor protection removed");
|
||||
+}
|
||||
+
|
||||
+MODULE_DESCRIPTION("AppArmor process confinement");
|
||||
+MODULE_AUTHOR("Novell/Immunix, http://bugs.opensuse.org");
|
||||
+MODULE_LICENSE("GPL");
|
1494
kernel-patches/2.6.28/apparmor-main.diff
Normal file
1494
kernel-patches/2.6.28/apparmor-main.diff
Normal file
File diff suppressed because it is too large
Load diff
1441
kernel-patches/2.6.28/apparmor-misc.diff
Normal file
1441
kernel-patches/2.6.28/apparmor-misc.diff
Normal file
File diff suppressed because it is too large
Load diff
1350
kernel-patches/2.6.28/apparmor-module_interface.diff
Normal file
1350
kernel-patches/2.6.28/apparmor-module_interface.diff
Normal file
File diff suppressed because it is too large
Load diff
408
kernel-patches/2.6.28/apparmor-network.diff
Normal file
408
kernel-patches/2.6.28/apparmor-network.diff
Normal file
|
@ -0,0 +1,408 @@
|
|||
From: John Johansen <jjohansen@suse.de>
|
||||
Subject: AppArmor: Simplified network controls for AppArmor
|
||||
|
||||
Simple network control determining which network families a confined
|
||||
application has access to.
|
||||
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
security/apparmor/Makefile | 7 +
|
||||
security/apparmor/apparmor.h | 9 ++
|
||||
security/apparmor/lsm.c | 129 ++++++++++++++++++++++++++++++++++-
|
||||
security/apparmor/main.c | 107 ++++++++++++++++++++++++++++-
|
||||
security/apparmor/module_interface.c | 26 ++++++-
|
||||
5 files changed, 271 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/security/apparmor/Makefile
|
||||
+++ b/security/apparmor/Makefile
|
||||
@@ -8,6 +8,11 @@ apparmor-y := main.o list.o procattr.o l
|
||||
quiet_cmd_make-caps = GEN $@
|
||||
cmd_make-caps = sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z > $@
|
||||
|
||||
-$(obj)/main.o : $(obj)/capability_names.h
|
||||
+quiet_cmd_make-af = GEN $@
|
||||
+cmd_make-af = sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z > $@
|
||||
+
|
||||
+$(obj)/main.o : $(obj)/capability_names.h $(obj)/af_names.h
|
||||
$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
|
||||
$(call cmd,make-caps)
|
||||
+$(obj)/af_names.h : $(srctree)/include/linux/socket.h
|
||||
+ $(call cmd,make-af)
|
||||
--- a/security/apparmor/apparmor.h
|
||||
+++ b/security/apparmor/apparmor.h
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/binfmts.h>
|
||||
#include <linux/rcupdate.h>
|
||||
+#include <linux/socket.h>
|
||||
+#include <net/sock.h>
|
||||
|
||||
/*
|
||||
* We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags
|
||||
@@ -212,6 +214,9 @@ struct aa_profile {
|
||||
struct list_head task_contexts;
|
||||
spinlock_t lock;
|
||||
unsigned long int_flags;
|
||||
+ u16 network_families[AF_MAX];
|
||||
+ u16 audit_network[AF_MAX];
|
||||
+ u16 quiet_network[AF_MAX];
|
||||
};
|
||||
|
||||
extern struct list_head profile_ns_list;
|
||||
@@ -258,6 +263,7 @@ struct aa_audit {
|
||||
int request_mask, denied_mask, audit_mask;
|
||||
struct iattr *iattr;
|
||||
pid_t task, parent;
|
||||
+ int family, type, protocol;
|
||||
int error_code;
|
||||
};
|
||||
|
||||
@@ -319,6 +325,9 @@ extern void aa_change_task_context(struc
|
||||
struct aa_profile *previous_profile);
|
||||
extern int aa_may_ptrace(struct aa_task_context *cxt,
|
||||
struct aa_profile *tracee);
|
||||
+extern int aa_net_perm(struct aa_profile *profile, char *operation,
|
||||
+ int family, int type, int protocol);
|
||||
+extern int aa_revalidate_sk(struct sock *sk, char *operation);
|
||||
|
||||
/* lsm.c */
|
||||
extern int apparmor_initialized;
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/audit.h>
|
||||
+#include <net/sock.h>
|
||||
|
||||
#include "apparmor.h"
|
||||
#include "inline.h"
|
||||
@@ -680,6 +681,117 @@ static void apparmor_task_free_security(
|
||||
aa_release(task);
|
||||
}
|
||||
|
||||
+static int apparmor_socket_create(int family, int type, int protocol, int kern)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (kern)
|
||||
+ return 0;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+ if (profile)
|
||||
+ error = aa_net_perm(profile, "socket_create", family,
|
||||
+ type, protocol);
|
||||
+ aa_put_profile(profile);
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_post_create(struct socket *sock, int family,
|
||||
+ int type, int protocol, int kern)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ if (kern)
|
||||
+ return 0;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_post_create");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_bind(struct socket *sock,
|
||||
+ struct sockaddr *address, int addrlen)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_bind");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_connect(struct socket *sock,
|
||||
+ struct sockaddr *address, int addrlen)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_connect");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_listen(struct socket *sock, int backlog)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_listen");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_accept");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_sendmsg(struct socket *sock,
|
||||
+ struct msghdr *msg, int size)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_sendmsg");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_recvmsg(struct socket *sock,
|
||||
+ struct msghdr *msg, int size, int flags)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_recvmsg");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_getsockname(struct socket *sock)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_getsockname");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_getpeername(struct socket *sock)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_getpeername");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_getsockopt(struct socket *sock, int level,
|
||||
+ int optname)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_getsockopt");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_setsockopt(struct socket *sock, int level,
|
||||
+ int optname)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_setsockopt");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_shutdown(struct socket *sock, int how)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_shutdown");
|
||||
+}
|
||||
+
|
||||
static int apparmor_getprocattr(struct task_struct *task, char *name,
|
||||
char **value)
|
||||
{
|
||||
@@ -780,9 +892,6 @@ struct security_operations apparmor_ops
|
||||
.capable = apparmor_capable,
|
||||
.syslog = cap_syslog,
|
||||
|
||||
- .netlink_send = cap_netlink_send,
|
||||
- .netlink_recv = cap_netlink_recv,
|
||||
-
|
||||
.bprm_apply_creds = cap_bprm_apply_creds,
|
||||
.bprm_set_security = apparmor_bprm_set_security,
|
||||
.bprm_secureexec = apparmor_bprm_secureexec,
|
||||
@@ -820,6 +929,20 @@ struct security_operations apparmor_ops
|
||||
|
||||
.getprocattr = apparmor_getprocattr,
|
||||
.setprocattr = apparmor_setprocattr,
|
||||
+
|
||||
+ .socket_create = apparmor_socket_create,
|
||||
+ .socket_post_create = apparmor_socket_post_create,
|
||||
+ .socket_bind = apparmor_socket_bind,
|
||||
+ .socket_connect = apparmor_socket_connect,
|
||||
+ .socket_listen = apparmor_socket_listen,
|
||||
+ .socket_accept = apparmor_socket_accept,
|
||||
+ .socket_sendmsg = apparmor_socket_sendmsg,
|
||||
+ .socket_recvmsg = apparmor_socket_recvmsg,
|
||||
+ .socket_getsockname = apparmor_socket_getsockname,
|
||||
+ .socket_getpeername = apparmor_socket_getpeername,
|
||||
+ .socket_getsockopt = apparmor_socket_getsockopt,
|
||||
+ .socket_setsockopt = apparmor_socket_setsockopt,
|
||||
+ .socket_shutdown = apparmor_socket_shutdown,
|
||||
};
|
||||
|
||||
void info_message(const char *str)
|
||||
--- a/security/apparmor/main.c
|
||||
+++ b/security/apparmor/main.c
|
||||
@@ -14,6 +14,9 @@
|
||||
#include <linux/audit.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/ptrace.h>
|
||||
+#include <linux/socket.h>
|
||||
+#include <linux/net.h>
|
||||
+#include <net/sock.h>
|
||||
|
||||
#include "apparmor.h"
|
||||
|
||||
@@ -116,6 +119,24 @@ static void aa_audit_file_mask(struct au
|
||||
audit_log_format(ab, " %s=\"%s::%s\"", name, user, other);
|
||||
}
|
||||
|
||||
+static const char *address_families[] = {
|
||||
+#include "af_names.h"
|
||||
+};
|
||||
+
|
||||
+static const char *sock_types[] = {
|
||||
+ "unknown(0)",
|
||||
+ "stream",
|
||||
+ "dgram",
|
||||
+ "raw",
|
||||
+ "rdm",
|
||||
+ "seqpacket",
|
||||
+ "dccp",
|
||||
+ "unknown(7)",
|
||||
+ "unknown(8)",
|
||||
+ "unknown(9)",
|
||||
+ "packet",
|
||||
+};
|
||||
+
|
||||
/**
|
||||
* aa_audit - Log an audit event to the audit subsystem
|
||||
* @profile: profile to check against
|
||||
@@ -187,7 +208,25 @@ static int aa_audit_base(struct aa_profi
|
||||
audit_log_untrustedstring(ab, sa->name2);
|
||||
}
|
||||
|
||||
- audit_log_format(ab, " pid=%d", current->pid);
|
||||
+ if (sa->family || sa->type) {
|
||||
+ if (address_families[sa->family])
|
||||
+ audit_log_format(ab, " family=\"%s\"",
|
||||
+ address_families[sa->family]);
|
||||
+ else
|
||||
+ audit_log_format(ab, " family=\"unknown(%d)\"",
|
||||
+ sa->family);
|
||||
+
|
||||
+ if (sock_types[sa->type])
|
||||
+ audit_log_format(ab, " sock_type=\"%s\"",
|
||||
+ sock_types[sa->type]);
|
||||
+ else
|
||||
+ audit_log_format(ab, " sock_type=\"unknown(%d)\"",
|
||||
+ sa->type);
|
||||
+
|
||||
+ audit_log_format(ab, " protocol=%d", sa->protocol);
|
||||
+ }
|
||||
+
|
||||
+ audit_log_format(ab, " pid=%d", current->pid);
|
||||
|
||||
if (profile) {
|
||||
audit_log_format(ab, " profile=");
|
||||
@@ -768,6 +807,72 @@ int aa_link(struct aa_profile *profile,
|
||||
|
||||
return error;
|
||||
}
|
||||
+
|
||||
+int aa_net_perm(struct aa_profile *profile, char *operation,
|
||||
+ int family, int type, int protocol)
|
||||
+{
|
||||
+ struct aa_audit sa;
|
||||
+ int error = 0;
|
||||
+ u16 family_mask, audit_mask, quiet_mask;
|
||||
+
|
||||
+ if ((family < 0) || (family >= AF_MAX))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if ((type < 0) || (type >= SOCK_MAX))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* unix domain and netlink sockets are handled by ipc */
|
||||
+ if (family == AF_UNIX || family == AF_NETLINK)
|
||||
+ return 0;
|
||||
+
|
||||
+ family_mask = profile->network_families[family];
|
||||
+ audit_mask = profile->audit_network[family];
|
||||
+ quiet_mask = profile->quiet_network[family];
|
||||
+
|
||||
+ error = (family_mask & (1 << type)) ? 0 : -EACCES;
|
||||
+
|
||||
+ memset(&sa, 0, sizeof(sa));
|
||||
+ sa.operation = operation;
|
||||
+ sa.gfp_mask = GFP_KERNEL;
|
||||
+ sa.family = family;
|
||||
+ sa.type = type;
|
||||
+ sa.protocol = protocol;
|
||||
+ sa.error_code = error;
|
||||
+
|
||||
+ if (likely(!error)) {
|
||||
+ if (!PROFILE_AUDIT(profile) && !(family_mask & audit_mask))
|
||||
+ return 0;
|
||||
+ } else if (!((1 << type) & ~quiet_mask)) {
|
||||
+ return error;
|
||||
+ }
|
||||
+
|
||||
+ error = aa_audit(profile, &sa);
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+int aa_revalidate_sk(struct sock *sk, char *operation)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+ int error = 0;
|
||||
+
|
||||
+ /* this is some debugging code to flush out the network hooks that
|
||||
+ that are called in interrupt context */
|
||||
+ if (in_interrupt()) {
|
||||
+ printk("AppArmor Debug: Hook being called from interrupt context\n");
|
||||
+ dump_stack();
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+ if (profile)
|
||||
+ error = aa_net_perm(profile, operation,
|
||||
+ sk->sk_family, sk->sk_type,
|
||||
+ sk->sk_protocol);
|
||||
+ aa_put_profile(profile);
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
|
||||
/*******************************
|
||||
* Global task related functions
|
||||
--- a/security/apparmor/module_interface.c
|
||||
+++ b/security/apparmor/module_interface.c
|
||||
@@ -321,8 +321,8 @@ static struct aa_profile *aa_unpack_prof
|
||||
struct aa_audit *sa)
|
||||
{
|
||||
struct aa_profile *profile = NULL;
|
||||
-
|
||||
- int error = -EPROTO;
|
||||
+ size_t size = 0;
|
||||
+ int i, error = -EPROTO;
|
||||
|
||||
profile = alloc_aa_profile();
|
||||
if (!profile)
|
||||
@@ -355,6 +355,28 @@ static struct aa_profile *aa_unpack_prof
|
||||
if (!aa_is_u32(e, &(profile->set_caps), NULL))
|
||||
goto fail;
|
||||
|
||||
+ size = aa_is_array(e, "net_allowed_af");
|
||||
+ if (size) {
|
||||
+ if (size > AF_MAX)
|
||||
+ goto fail;
|
||||
+
|
||||
+ for (i = 0; i < size; i++) {
|
||||
+ if (!aa_is_u16(e, &profile->network_families[i], NULL))
|
||||
+ goto fail;
|
||||
+ if (!aa_is_u16(e, &profile->audit_network[i], NULL))
|
||||
+ goto fail;
|
||||
+ if (!aa_is_u16(e, &profile->quiet_network[i], NULL))
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
|
||||
+ goto fail;
|
||||
+ /* allow unix domain and netlink sockets they are handled
|
||||
+ * by IPC
|
||||
+ */
|
||||
+ }
|
||||
+ profile->network_families[AF_UNIX] = 0xffff;
|
||||
+ profile->network_families[AF_NETLINK] = 0xffff;
|
||||
+
|
||||
/* get file rules */
|
||||
profile->file_rules = aa_unpack_dfa(e);
|
||||
if (IS_ERR(profile->file_rules)) {
|
78
kernel-patches/2.6.28/apparmor-path_permission
Normal file
78
kernel-patches/2.6.28/apparmor-path_permission
Normal file
|
@ -0,0 +1,78 @@
|
|||
From: Jeff Mahoney <jeffm@suse.com>
|
||||
Subject: [PATCH] apparmor: convert apparmor_inode_permission to path
|
||||
|
||||
patches.apparmor/add-security_path_permission added the ->path_permission
|
||||
call. This patch converts apparmor_inode_permission to
|
||||
apparmor_path_permission. The former is now a pass-all, which is how
|
||||
it behaved in 2.6.26 if a NULL nameidata was passed.
|
||||
|
||||
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
security/apparmor/lsm.c | 41 +++++++++++++++++++++++++++--------------
|
||||
1 file changed, 27 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -448,21 +448,9 @@ out:
|
||||
return error;
|
||||
}
|
||||
|
||||
-static int apparmor_inode_permission(struct inode *inode, int mask,
|
||||
- struct nameidata *nd)
|
||||
+static int apparmor_inode_permission(struct inode *inode, int mask)
|
||||
{
|
||||
- int check = 0;
|
||||
-
|
||||
- if (!nd || nd->flags & (LOOKUP_PARENT | LOOKUP_CONTINUE))
|
||||
- return 0;
|
||||
- mask = aa_mask_permissions(mask);
|
||||
- if (S_ISDIR(inode->i_mode)) {
|
||||
- check |= AA_CHECK_DIR;
|
||||
- /* allow traverse accesses to directories */
|
||||
- mask &= ~MAY_EXEC;
|
||||
- }
|
||||
- return aa_permission("inode_permission", inode, nd->dentry, nd->mnt,
|
||||
- mask, check);
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static int apparmor_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
@@ -656,6 +644,29 @@ static int apparmor_file_mprotect(struct
|
||||
!(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
|
||||
}
|
||||
|
||||
+static int apparmor_path_permission(struct path *path, int mask)
|
||||
+{
|
||||
+ struct inode *inode;
|
||||
+ int check = 0;
|
||||
+
|
||||
+ if (!path)
|
||||
+ return 0;
|
||||
+
|
||||
+ inode = path->dentry->d_inode;
|
||||
+
|
||||
+ mask = aa_mask_permissions(mask);
|
||||
+ if (S_ISDIR(inode->i_mode)) {
|
||||
+ check |= AA_CHECK_DIR;
|
||||
+ /* allow traverse accesses to directories */
|
||||
+ mask &= ~MAY_EXEC;
|
||||
+ if (!mask)
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return aa_permission("inode_permission", inode, path->dentry,
|
||||
+ path->mnt, mask, check);
|
||||
+}
|
||||
+
|
||||
static int apparmor_task_alloc_security(struct task_struct *task)
|
||||
{
|
||||
return aa_clone(task);
|
||||
@@ -800,6 +811,8 @@ struct security_operations apparmor_ops
|
||||
.file_mprotect = apparmor_file_mprotect,
|
||||
.file_lock = apparmor_file_lock,
|
||||
|
||||
+ .path_permission = apparmor_path_permission,
|
||||
+
|
||||
.task_alloc_security = apparmor_task_alloc_security,
|
||||
.task_free_security = apparmor_task_free_security,
|
||||
.task_post_setuid = cap_task_post_setuid,
|
113
kernel-patches/2.6.28/apparmor-ptrace-2.6.27.diff
Normal file
113
kernel-patches/2.6.28/apparmor-ptrace-2.6.27.diff
Normal file
|
@ -0,0 +1,113 @@
|
|||
From: Jeff Mahoney <jeffm@suse.com>
|
||||
Subject: apparmor: use new ptrace security_operations
|
||||
|
||||
This patch implements the new ptrace security_operations members.
|
||||
|
||||
->ptrace was changed to ->ptrace_may_access and ->ptrace_traceme.
|
||||
|
||||
The apparmor versions are really just wrappers for the old function.
|
||||
|
||||
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
security/apparmor/lsm.c | 51 ++++++++++++++++++++++++++++++------------------
|
||||
1 file changed, 32 insertions(+), 19 deletions(-)
|
||||
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -157,47 +157,47 @@ static int aa_reject_syscall(struct task
|
||||
return error;
|
||||
}
|
||||
|
||||
-static int apparmor_ptrace(struct task_struct *parent,
|
||||
- struct task_struct *child, unsigned int mode)
|
||||
+static int apparmor_ptrace(struct task_struct *tracer,
|
||||
+ struct task_struct *tracee)
|
||||
{
|
||||
struct aa_task_context *cxt;
|
||||
int error = 0;
|
||||
|
||||
/*
|
||||
- * parent can ptrace child when
|
||||
- * - parent is unconfined
|
||||
- * - parent & child are in the same namespace &&
|
||||
- * - parent is in complain mode
|
||||
- * - parent and child are confined by the same profile
|
||||
- * - parent profile has CAP_SYS_PTRACE
|
||||
+ * tracer can ptrace tracee when
|
||||
+ * - tracer is unconfined
|
||||
+ * - tracer & tracee are in the same namespace &&
|
||||
+ * - tracer is in complain mode
|
||||
+ * - tracer and tracee are confined by the same profile
|
||||
+ * - tracer profile has CAP_SYS_PTRACE
|
||||
*/
|
||||
|
||||
rcu_read_lock();
|
||||
- cxt = aa_task_context(parent);
|
||||
+ cxt = aa_task_context(tracer);
|
||||
if (cxt) {
|
||||
- if (parent->nsproxy != child->nsproxy) {
|
||||
+ if (tracer->nsproxy != tracee->nsproxy) {
|
||||
struct aa_audit sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.operation = "ptrace";
|
||||
sa.gfp_mask = GFP_ATOMIC;
|
||||
- sa.parent = parent->pid;
|
||||
- sa.task = child->pid;
|
||||
+ sa.parent = tracer->pid;
|
||||
+ sa.task = tracee->pid;
|
||||
sa.info = "different namespaces";
|
||||
aa_audit_reject(cxt->profile, &sa);
|
||||
error = -EPERM;
|
||||
} else {
|
||||
- struct aa_task_context *child_cxt =
|
||||
- aa_task_context(child);
|
||||
+ struct aa_task_context *tracee_cxt =
|
||||
+ aa_task_context(tracee);
|
||||
|
||||
- error = aa_may_ptrace(cxt, child_cxt ?
|
||||
- child_cxt->profile : NULL);
|
||||
+ error = aa_may_ptrace(cxt, tracee_cxt ?
|
||||
+ tracee_cxt->profile : NULL);
|
||||
if (error && PROFILE_COMPLAIN(cxt->profile)) {
|
||||
struct aa_audit sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.operation = "ptrace";
|
||||
sa.gfp_mask = GFP_ATOMIC;
|
||||
- sa.parent = parent->pid;
|
||||
- sa.task = child->pid;
|
||||
+ sa.parent = tracer->pid;
|
||||
+ sa.task = tracee->pid;
|
||||
aa_audit_hint(cxt->profile, &sa);
|
||||
}
|
||||
}
|
||||
@@ -207,6 +207,18 @@ static int apparmor_ptrace(struct task_s
|
||||
return error;
|
||||
}
|
||||
|
||||
+static int apparmor_ptrace_may_access(struct task_struct *child,
|
||||
+ unsigned int mode)
|
||||
+{
|
||||
+ return apparmor_ptrace(current, child);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int apparmor_ptrace_traceme(struct task_struct *parent)
|
||||
+{
|
||||
+ return apparmor_ptrace(parent, current);
|
||||
+}
|
||||
+
|
||||
static int apparmor_capable(struct task_struct *task, int cap)
|
||||
{
|
||||
int error;
|
||||
@@ -899,7 +911,8 @@ static int apparmor_task_setrlimit(unsig
|
||||
}
|
||||
|
||||
struct security_operations apparmor_ops = {
|
||||
- .ptrace = apparmor_ptrace,
|
||||
+ .ptrace_may_access = apparmor_ptrace_may_access,
|
||||
+ .ptrace_traceme = apparmor_ptrace_traceme,
|
||||
.capget = cap_capget,
|
||||
.capset_check = cap_capset_check,
|
||||
.capset_set = cap_capset_set,
|
461
kernel-patches/2.6.28/apparmor-rlimits.diff
Normal file
461
kernel-patches/2.6.28/apparmor-rlimits.diff
Normal file
|
@ -0,0 +1,461 @@
|
|||
From: John Johansen <jjohansen@suse.de>
|
||||
Subject: AppArmor: per profile controls for system rlimits
|
||||
|
||||
Provide contol of rlimits on a per profile basis. Each profile provides
|
||||
a per limit contol and corresponding hard limit value, such that when a
|
||||
profile becomes attached to a task it sets the tasks limits to be <= to
|
||||
the profiles specified limits. Note: the profile limit value will not
|
||||
raise a tasks limit if it is already less than the profile mandates.
|
||||
|
||||
In addition to setting a tasks limits, the ability to set limits on
|
||||
a confined task are controlled. AppArmor only controls the raising
|
||||
of a tasks limits Tasks with CAP_SYS_RESOURCE can have their hard limits
|
||||
raised up to the value specified by the profile. AppArmor does not
|
||||
prevent a task for lowering its hard limits, nor does it provide
|
||||
additional control on soft limits.
|
||||
|
||||
AppArmor only controls the limits specified in a profile so that
|
||||
any limit not specified is free to be modified subject to standard
|
||||
linux limitations.
|
||||
|
||||
---
|
||||
security/apparmor/apparmor.h | 23 ++++++
|
||||
security/apparmor/apparmorfs.c | 2
|
||||
security/apparmor/lsm.c | 16 ++++
|
||||
security/apparmor/main.c | 132 +++++++++++++++++++++++++++++++----
|
||||
security/apparmor/module_interface.c | 56 ++++++++++++++
|
||||
5 files changed, 215 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/security/apparmor/apparmor.h
|
||||
+++ b/security/apparmor/apparmor.h
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/binfmts.h>
|
||||
#include <linux/rcupdate.h>
|
||||
+#include <linux/resource.h>
|
||||
#include <linux/socket.h>
|
||||
#include <net/sock.h>
|
||||
|
||||
@@ -139,6 +140,18 @@ extern unsigned int apparmor_path_max;
|
||||
|
||||
#define AA_ERROR(fmt, args...) printk(KERN_ERR "AppArmor: " fmt, ##args)
|
||||
|
||||
+/* struct aa_rlimit - rlimits settings for the profile
|
||||
+ * @mask: which hard limits to set
|
||||
+ * @limits: rlimit values that override task limits
|
||||
+ *
|
||||
+ * AppArmor rlimits are used to set confined task rlimits. Only the
|
||||
+ * limits specified in @mask will be controlled by apparmor.
|
||||
+ */
|
||||
+struct aa_rlimit {
|
||||
+ unsigned int mask;
|
||||
+ struct rlimit limits[RLIM_NLIMITS];
|
||||
+};
|
||||
+
|
||||
struct aa_profile;
|
||||
|
||||
/* struct aa_namespace - namespace for a set of profiles
|
||||
@@ -173,6 +186,8 @@ struct aa_namespace {
|
||||
* @audit_caps: caps that are to be audited
|
||||
* @quiet_caps: caps that should not be audited
|
||||
* @capabilities: capabilities granted by the process
|
||||
+ * @rlimits: rlimits for the profile
|
||||
+ * @task_count: how many tasks the profile is attached to
|
||||
* @count: reference count of the profile
|
||||
* @task_contexts: list of tasks confined by profile
|
||||
* @lock: lock for the task_contexts list
|
||||
@@ -210,6 +225,9 @@ struct aa_profile {
|
||||
kernel_cap_t audit_caps;
|
||||
kernel_cap_t quiet_caps;
|
||||
|
||||
+ struct aa_rlimit rlimits;
|
||||
+ unsigned int task_count;
|
||||
+
|
||||
struct kref count;
|
||||
struct list_head task_contexts;
|
||||
spinlock_t lock;
|
||||
@@ -261,6 +279,7 @@ struct aa_audit {
|
||||
const char *name2;
|
||||
const char *name3;
|
||||
int request_mask, denied_mask, audit_mask;
|
||||
+ int rlimit;
|
||||
struct iattr *iattr;
|
||||
pid_t task, parent;
|
||||
int family, type, protocol;
|
||||
@@ -328,6 +347,10 @@ extern int aa_may_ptrace(struct aa_task_
|
||||
extern int aa_net_perm(struct aa_profile *profile, char *operation,
|
||||
int family, int type, int protocol);
|
||||
extern int aa_revalidate_sk(struct sock *sk, char *operation);
|
||||
+extern int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
|
||||
+ struct rlimit *new_rlim);
|
||||
+extern void aa_set_rlimits(struct task_struct *task, struct aa_profile *profile);
|
||||
+
|
||||
|
||||
/* lsm.c */
|
||||
extern int apparmor_initialized;
|
||||
--- a/security/apparmor/apparmorfs.c
|
||||
+++ b/security/apparmor/apparmorfs.c
|
||||
@@ -106,7 +106,7 @@ static ssize_t aa_features_read(struct f
|
||||
{
|
||||
const char *features = "file=3.0 capability=2.0 network=1.0 "
|
||||
"change_hat=1.5 change_profile=1.0 "
|
||||
- "aanamespaces=1.0";
|
||||
+ "aanamespaces=1.0 rlimit=1.0";
|
||||
|
||||
return simple_read_from_buffer(buf, size, ppos, features,
|
||||
strlen(features));
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -883,6 +883,21 @@ static int apparmor_setprocattr(struct t
|
||||
return error;
|
||||
}
|
||||
|
||||
+static int apparmor_task_setrlimit(unsigned int resource,
|
||||
+ struct rlimit *new_rlim)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+ int error = 0;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+ if (profile) {
|
||||
+ error = aa_task_setrlimit(profile, resource, new_rlim);
|
||||
+ }
|
||||
+ aa_put_profile(profile);
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
struct security_operations apparmor_ops = {
|
||||
.ptrace = apparmor_ptrace,
|
||||
.capget = cap_capget,
|
||||
@@ -926,6 +941,7 @@ struct security_operations apparmor_ops
|
||||
.task_free_security = apparmor_task_free_security,
|
||||
.task_post_setuid = cap_task_post_setuid,
|
||||
.task_reparent_to_init = cap_task_reparent_to_init,
|
||||
+ .task_setrlimit = apparmor_task_setrlimit,
|
||||
|
||||
.getprocattr = apparmor_getprocattr,
|
||||
.setprocattr = apparmor_setprocattr,
|
||||
--- a/security/apparmor/main.c
|
||||
+++ b/security/apparmor/main.c
|
||||
@@ -177,6 +177,9 @@ static int aa_audit_base(struct aa_profi
|
||||
if (sa->request_mask)
|
||||
audit_log_format(ab, " fsuid=%d", current->fsuid);
|
||||
|
||||
+ if (sa->rlimit)
|
||||
+ audit_log_format(ab, " rlimit=%d", sa->rlimit - 1);
|
||||
+
|
||||
if (sa->iattr) {
|
||||
struct iattr *iattr = sa->iattr;
|
||||
|
||||
@@ -873,6 +876,79 @@ int aa_revalidate_sk(struct sock *sk, ch
|
||||
|
||||
return error;
|
||||
}
|
||||
+/**
|
||||
+ * aa_task_setrlimit - test permission to set an rlimit
|
||||
+ * @profile - profile confining the task
|
||||
+ * @resource - the resource being set
|
||||
+ * @new_rlim - the new resource limit
|
||||
+ *
|
||||
+ * Control raising the processes hard limit.
|
||||
+ */
|
||||
+int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
|
||||
+ struct rlimit *new_rlim)
|
||||
+{
|
||||
+ struct aa_audit sa;
|
||||
+ int error = 0;
|
||||
+
|
||||
+ memset(&sa, 0, sizeof(sa));
|
||||
+ sa.operation = "setrlimit";
|
||||
+ sa.gfp_mask = GFP_KERNEL;
|
||||
+ sa.rlimit = resource + 1;
|
||||
+
|
||||
+ if (profile->rlimits.mask & (1 << resource) &&
|
||||
+ new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max) {
|
||||
+ sa.error_code = -EACCES;
|
||||
+
|
||||
+ error = aa_audit(profile, &sa);
|
||||
+ }
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int aa_rlimit_nproc(struct aa_profile *profile) {
|
||||
+ if (profile && (profile->rlimits.mask & (1 << RLIMIT_NPROC)) &&
|
||||
+ profile->task_count >= profile->rlimits.limits[RLIMIT_NPROC].rlim_max)
|
||||
+ return -EAGAIN;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void aa_set_rlimits(struct task_struct *task, struct aa_profile *profile)
|
||||
+{
|
||||
+ int i, mask;
|
||||
+
|
||||
+ if (!profile)
|
||||
+ return;
|
||||
+
|
||||
+ if (!profile->rlimits.mask)
|
||||
+ return;
|
||||
+
|
||||
+ task_lock(task->group_leader);
|
||||
+ mask = 1;
|
||||
+ for (i = 0; i < RLIM_NLIMITS; i++, mask <<= 1) {
|
||||
+ struct rlimit new_rlim, *old_rlim;
|
||||
+
|
||||
+ /* check to see if NPROC which is per profile and handled
|
||||
+ * in clone/exec or whether this is a limit to be set
|
||||
+ * can't set cpu limit either right now
|
||||
+ */
|
||||
+ if (i == RLIMIT_NPROC || i == RLIMIT_CPU)
|
||||
+ continue;
|
||||
+
|
||||
+ old_rlim = task->signal->rlim + i;
|
||||
+ new_rlim = *old_rlim;
|
||||
+
|
||||
+ if (mask & profile->rlimits.mask &&
|
||||
+ profile->rlimits.limits[i].rlim_max < new_rlim.rlim_max) {
|
||||
+ new_rlim.rlim_max = profile->rlimits.limits[i].rlim_max;
|
||||
+ /* soft limit should not exceed hard limit */
|
||||
+ if (new_rlim.rlim_cur > new_rlim.rlim_max)
|
||||
+ new_rlim.rlim_cur = new_rlim.rlim_max;
|
||||
+ }
|
||||
+
|
||||
+ *old_rlim = new_rlim;
|
||||
+ }
|
||||
+ task_unlock(task->group_leader);
|
||||
+}
|
||||
|
||||
/*******************************
|
||||
* Global task related functions
|
||||
@@ -886,6 +962,7 @@ int aa_revalidate_sk(struct sock *sk, ch
|
||||
*/
|
||||
int aa_clone(struct task_struct *child)
|
||||
{
|
||||
+ struct aa_audit sa;
|
||||
struct aa_task_context *cxt, *child_cxt;
|
||||
struct aa_profile *profile;
|
||||
|
||||
@@ -895,6 +972,11 @@ int aa_clone(struct task_struct *child)
|
||||
if (!child_cxt)
|
||||
return -ENOMEM;
|
||||
|
||||
+ memset(&sa, 0, sizeof(sa));
|
||||
+ sa.operation = "clone";
|
||||
+ sa.task = child->pid;
|
||||
+ sa.gfp_mask = GFP_KERNEL;
|
||||
+
|
||||
repeat:
|
||||
profile = aa_get_profile(current);
|
||||
if (profile) {
|
||||
@@ -911,18 +993,22 @@ repeat:
|
||||
goto repeat;
|
||||
}
|
||||
|
||||
+ if (aa_rlimit_nproc(profile)) {
|
||||
+ sa.info = "rlimit nproc limit exceeded";
|
||||
+ unlock_profile(profile);
|
||||
+ aa_audit_reject(profile, &sa);
|
||||
+ aa_put_profile(profile);
|
||||
+ return -EAGAIN;
|
||||
+ }
|
||||
+
|
||||
/* No need to grab the child's task lock here. */
|
||||
aa_change_task_context(child, child_cxt, profile,
|
||||
cxt->cookie, cxt->previous_profile);
|
||||
+
|
||||
unlock_profile(profile);
|
||||
|
||||
if (APPARMOR_COMPLAIN(child_cxt) &&
|
||||
profile == profile->ns->null_complain_profile) {
|
||||
- struct aa_audit sa;
|
||||
- memset(&sa, 0, sizeof(sa));
|
||||
- sa.operation = "clone";
|
||||
- sa.gfp_mask = GFP_KERNEL;
|
||||
- sa.task = child->pid;
|
||||
aa_audit_hint(profile, &sa);
|
||||
}
|
||||
aa_put_profile(profile);
|
||||
@@ -1157,6 +1243,10 @@ repeat:
|
||||
sa.task = current->parent->pid;
|
||||
aa_audit_reject(profile, &sa);
|
||||
}
|
||||
+ if (PTR_ERR(old_profile) == -EAGAIN) {
|
||||
+ sa.info = "rlimit nproc limit exceeded";
|
||||
+ aa_audit_reject(profile, &sa);
|
||||
+ }
|
||||
new_profile = old_profile;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -1304,6 +1394,12 @@ static int do_change_profile(struct aa_p
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ if ((error = aa_rlimit_nproc(new_profile))) {
|
||||
+ sa->info = "rlimit nproc limit exceeded";
|
||||
+ aa_audit_reject(cxt->profile, sa);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
if (new_profile == ns->null_complain_profile)
|
||||
aa_audit_hint(cxt->profile, sa);
|
||||
|
||||
@@ -1482,17 +1578,18 @@ struct aa_profile *__aa_replace_profile(
|
||||
|
||||
cxt = lock_task_and_profiles(task, profile);
|
||||
if (unlikely(profile && profile->isstale)) {
|
||||
- task_unlock(task);
|
||||
- unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
|
||||
- aa_free_task_context(new_cxt);
|
||||
- return ERR_PTR(-ESTALE);
|
||||
+ old_profile = ERR_PTR(-ESTALE);
|
||||
+ goto error;
|
||||
}
|
||||
|
||||
if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, profile)) {
|
||||
- task_unlock(task);
|
||||
- unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
|
||||
- aa_free_task_context(new_cxt);
|
||||
- return ERR_PTR(-EPERM);
|
||||
+ old_profile = ERR_PTR(-EPERM);
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ if (aa_rlimit_nproc(profile)) {
|
||||
+ old_profile = ERR_PTR(-EAGAIN);
|
||||
+ goto error;
|
||||
}
|
||||
|
||||
if (cxt)
|
||||
@@ -1500,8 +1597,15 @@ struct aa_profile *__aa_replace_profile(
|
||||
aa_change_task_context(task, new_cxt, profile, 0, NULL);
|
||||
|
||||
task_unlock(task);
|
||||
+ aa_set_rlimits(task, profile);
|
||||
unlock_both_profiles(profile, old_profile);
|
||||
return old_profile;
|
||||
+
|
||||
+error:
|
||||
+ task_unlock(task);
|
||||
+ unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
|
||||
+ aa_free_task_context(new_cxt);
|
||||
+ return old_profile;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1566,6 +1670,7 @@ void aa_change_task_context(struct task_
|
||||
|
||||
if (old_cxt) {
|
||||
list_del_init(&old_cxt->list);
|
||||
+ old_cxt->profile->task_count--;
|
||||
call_rcu(&old_cxt->rcu, free_aa_task_context_rcu_callback);
|
||||
}
|
||||
if (new_cxt) {
|
||||
@@ -1577,6 +1682,7 @@ void aa_change_task_context(struct task_
|
||||
new_cxt->cookie = cookie;
|
||||
new_cxt->task = task;
|
||||
new_cxt->profile = aa_dup_profile(profile);
|
||||
+ profile->task_count++;
|
||||
new_cxt->previous_profile = aa_dup_profile(previous_profile);
|
||||
list_move(&new_cxt->list, &profile->task_contexts);
|
||||
}
|
||||
--- a/security/apparmor/module_interface.c
|
||||
+++ b/security/apparmor/module_interface.c
|
||||
@@ -177,6 +177,22 @@ fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int aa_is_u64(struct aa_ext *e, u64 *data, const char *name)
|
||||
+{
|
||||
+ void *pos = e->pos;
|
||||
+ if (aa_is_nameX(e, AA_U64, name)) {
|
||||
+ if (!aa_inbounds(e, sizeof(u64)))
|
||||
+ goto fail;
|
||||
+ if (data)
|
||||
+ *data = le64_to_cpu(get_unaligned((u64 *)e->pos));
|
||||
+ e->pos += sizeof(u64);
|
||||
+ return 1;
|
||||
+ }
|
||||
+fail:
|
||||
+ e->pos = pos;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static size_t aa_is_array(struct aa_ext *e, const char *name)
|
||||
{
|
||||
void *pos = e->pos;
|
||||
@@ -312,6 +328,39 @@ fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int aa_unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
|
||||
+{
|
||||
+ void *pos = e->pos;
|
||||
+
|
||||
+ /* rlimits are optional */
|
||||
+ if (aa_is_nameX(e, AA_STRUCT, "rlimits")) {
|
||||
+ int i, size;
|
||||
+ u32 tmp = 0;
|
||||
+ if (!aa_is_u32(e, &tmp, NULL))
|
||||
+ goto fail;
|
||||
+ profile->rlimits.mask = tmp;
|
||||
+
|
||||
+ size = aa_is_array(e, NULL);
|
||||
+ if (size > RLIM_NLIMITS)
|
||||
+ goto fail;
|
||||
+ for (i = 0; i < size; i++) {
|
||||
+ u64 tmp = 0;
|
||||
+ if (!aa_is_u64(e, &tmp, NULL))
|
||||
+ goto fail;
|
||||
+ profile->rlimits.limits[i].rlim_max = tmp;
|
||||
+ }
|
||||
+ if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
|
||||
+ goto fail;
|
||||
+ if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ return 1;
|
||||
+
|
||||
+fail:
|
||||
+ e->pos = pos;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* aa_unpack_profile - unpack a serialized profile
|
||||
* @e: serialized data extent information
|
||||
@@ -355,6 +404,9 @@ static struct aa_profile *aa_unpack_prof
|
||||
if (!aa_is_u32(e, &(profile->set_caps), NULL))
|
||||
goto fail;
|
||||
|
||||
+ if (!aa_unpack_rlimits(e, profile))
|
||||
+ goto fail;
|
||||
+
|
||||
size = aa_is_array(e, "net_allowed_af");
|
||||
if (size) {
|
||||
if (size > AF_MAX)
|
||||
@@ -614,6 +666,8 @@ ssize_t aa_replace_profile(void *udata,
|
||||
sa.operation = "profile_load";
|
||||
goto out;
|
||||
}
|
||||
+ /* do not fail replacement based off of profile's NPROC rlimit */
|
||||
+
|
||||
/*
|
||||
* Replacement needs to allocate a new aa_task_context for each
|
||||
* task confined by old_profile. To do this the profile locks
|
||||
@@ -634,6 +688,7 @@ ssize_t aa_replace_profile(void *udata,
|
||||
task_lock(task);
|
||||
task_replace(task, new_cxt, new_profile);
|
||||
task_unlock(task);
|
||||
+ aa_set_rlimits(task, new_profile);
|
||||
new_cxt = NULL;
|
||||
}
|
||||
unlock_both_profiles(old_profile, new_profile);
|
||||
@@ -656,6 +711,7 @@ out:
|
||||
*
|
||||
* remove a profile from the profile list and all aa_task_context references
|
||||
* to said profile.
|
||||
+ * NOTE: removing confinement does not restore rlimits to preconfinemnet values
|
||||
*/
|
||||
ssize_t aa_remove_profile(char *name, size_t size)
|
||||
{
|
87
kernel-patches/2.6.28/aufs/aa-hack
Normal file
87
kernel-patches/2.6.28/aufs/aa-hack
Normal file
|
@ -0,0 +1,87 @@
|
|||
From: Jeff Mahoney <jeffm@suse.com>
|
||||
Subject: aufs: AppArmor compatibility
|
||||
|
||||
This patch adds NULL vfsmounts for AppArmor enabled kernels.
|
||||
|
||||
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
fs/aufs25/vfsub.c | 18 +++++++++---------
|
||||
1 file changed, 9 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/fs/aufs25/vfsub.c
|
||||
+++ b/fs/aufs25/vfsub.c
|
||||
@@ -127,9 +127,9 @@ int do_vfsub_create(struct inode *dir, s
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
|
||||
-#define VfsubSymlinkArgs dir, dentry, symname
|
||||
+#define VfsubSymlinkArgs dir, dentry, NULL, symname
|
||||
#else
|
||||
-#define VfsubSymlinkArgs dir, dentry, symname, mode
|
||||
+#define VfsubSymlinkArgs dir, dentry, NULL, symname, mode
|
||||
#endif
|
||||
|
||||
int do_vfsub_symlink(struct inode *dir, struct dentry *dentry,
|
||||
@@ -158,7 +158,7 @@ int do_vfsub_mknod(struct inode *dir, st
|
||||
LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, AuDLNPair(dentry), mode);
|
||||
IMustLock(dir);
|
||||
|
||||
- err = vfs_mknod(dir, dentry, mode, dev);
|
||||
+ err = vfs_mknod(dir, dentry, NULL, mode, dev);
|
||||
if (!err) {
|
||||
/* dir inode is locked */
|
||||
au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
|
||||
@@ -177,7 +177,7 @@ int do_vfsub_link(struct dentry *src_den
|
||||
IMustLock(dir);
|
||||
|
||||
lockdep_off();
|
||||
- err = vfs_link(src_dentry, dir, dentry);
|
||||
+ err = vfs_link(src_dentry, NULL, dir, dentry, 0);
|
||||
lockdep_on();
|
||||
if (!err) {
|
||||
LKTRTrace("src_i %p, dst_i %p\n",
|
||||
@@ -203,7 +203,7 @@ int do_vfsub_rename(struct inode *src_di
|
||||
IMustLock(src_dir);
|
||||
|
||||
lockdep_off();
|
||||
- err = vfs_rename(src_dir, src_dentry, dir, dentry);
|
||||
+ err = vfs_rename(src_dir, src_dentry, NULL, dir, dentry, 0);
|
||||
lockdep_on();
|
||||
if (!err) {
|
||||
/* dir inode is locked */
|
||||
@@ -221,7 +221,7 @@ int do_vfsub_mkdir(struct inode *dir, st
|
||||
LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, AuDLNPair(dentry), mode);
|
||||
IMustLock(dir);
|
||||
|
||||
- err = vfs_mkdir(dir, dentry, mode);
|
||||
+ err = vfs_mkdir(dir, dentry, NULL, mode);
|
||||
if (!err) {
|
||||
/* dir inode is locked */
|
||||
au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
|
||||
@@ -238,7 +238,7 @@ int do_vfsub_rmdir(struct inode *dir, st
|
||||
IMustLock(dir);
|
||||
|
||||
lockdep_off();
|
||||
- err = vfs_rmdir(dir, dentry);
|
||||
+ err = vfs_rmdir(dir, dentry, 0);
|
||||
lockdep_on();
|
||||
/* dir inode is locked */
|
||||
if (!err)
|
||||
@@ -255,7 +255,7 @@ int do_vfsub_unlink(struct inode *dir, s
|
||||
|
||||
/* vfs_unlink() locks inode */
|
||||
lockdep_off();
|
||||
- err = vfs_unlink(dir, dentry);
|
||||
+ err = vfs_unlink(dir, dentry, 0);
|
||||
lockdep_on();
|
||||
/* dir inode is locked */
|
||||
if (!err)
|
||||
@@ -493,7 +493,7 @@ static void call_notify_change(void *arg
|
||||
if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
|
||||
vfsub_ignore(a->vargs);
|
||||
lockdep_off();
|
||||
- *a->errp = notify_change(a->h_dentry, a->ia);
|
||||
+ *a->errp = notify_change(a->h_dentry, NULL, a->ia);
|
||||
lockdep_on();
|
||||
if (!*a->errp)
|
||||
au_update_fuse_h_inode(NULL, a->h_dentry); /*ignore*/
|
179
kernel-patches/2.6.28/aufs/aufs-fsetattr
Normal file
179
kernel-patches/2.6.28/aufs/aufs-fsetattr
Normal file
|
@ -0,0 +1,179 @@
|
|||
From: Jeff Mahoney <jeffm@suse.com>
|
||||
Subject: Add fsetattr
|
||||
|
||||
An AppArmor patch removed ia_file and ATTR_FILE from struct iattr and
|
||||
replaced it with the fsetattr file_operation.
|
||||
|
||||
This patch fixes aufs to use it.
|
||||
|
||||
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
fs/aufs25/dir.c | 1 +
|
||||
fs/aufs25/f_op.c | 1 +
|
||||
fs/aufs25/i_op.c | 25 ++++++++++++++-----------
|
||||
fs/aufs25/inode.h | 1 +
|
||||
fs/aufs25/misc.c | 5 ++---
|
||||
fs/aufs25/vfsub.c | 13 ++++++++++---
|
||||
fs/aufs25/vfsub.h | 2 ++
|
||||
7 files changed, 31 insertions(+), 17 deletions(-)
|
||||
|
||||
--- a/fs/aufs25/dir.c
|
||||
+++ b/fs/aufs25/dir.c
|
||||
@@ -546,4 +546,5 @@ struct file_operations aufs_dir_fop = {
|
||||
.release = aufs_release_dir,
|
||||
.flush = aufs_flush,
|
||||
.fsync = aufs_fsync_dir,
|
||||
+ .fsetattr = aufs_fsetattr,
|
||||
};
|
||||
--- a/fs/aufs25/f_op.c
|
||||
+++ b/fs/aufs25/f_op.c
|
||||
@@ -665,4 +665,5 @@ struct file_operations aufs_file_fop = {
|
||||
.splice_write = aufs_splice_write,
|
||||
.splice_read = aufs_splice_read,
|
||||
#endif
|
||||
+ .fsetattr = aufs_fsetattr,
|
||||
};
|
||||
--- a/fs/aufs25/i_op.c
|
||||
+++ b/fs/aufs25/i_op.c
|
||||
@@ -727,13 +727,13 @@ static int au_lock_and_icpup(struct dent
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
|
||||
+static int aufs_do_setattr(struct dentry *dentry, struct iattr *ia,
|
||||
+ struct file *file)
|
||||
{
|
||||
int err;
|
||||
struct inode *inode;
|
||||
struct super_block *sb;
|
||||
__u32 events;
|
||||
- struct file *file;
|
||||
loff_t sz;
|
||||
struct au_icpup_args *a;
|
||||
|
||||
@@ -751,12 +751,8 @@ static int aufs_setattr(struct dentry *d
|
||||
si_read_lock(sb, AuLock_FLUSH);
|
||||
vfsub_args_init(&a->vargs, a->ign, au_test_dlgt(au_mntflags(sb)), 0);
|
||||
|
||||
- if (ia->ia_valid & ATTR_FILE) {
|
||||
- /* currently ftruncate(2) only */
|
||||
- file = ia->ia_file;
|
||||
+ if (file)
|
||||
fi_write_lock(file);
|
||||
- ia->ia_file = au_h_fptr(file, au_fbstart(file));
|
||||
- }
|
||||
|
||||
sz = -1;
|
||||
if ((ia->ia_valid & ATTR_SIZE)
|
||||
@@ -800,11 +796,8 @@ static int aufs_setattr(struct dentry *d
|
||||
au_unpin(&a->pin);
|
||||
di_write_unlock(dentry);
|
||||
out_si:
|
||||
- if (file) {
|
||||
+ if (file)
|
||||
fi_write_unlock(file);
|
||||
- ia->ia_file = file;
|
||||
- ia->ia_valid |= ATTR_FILE;
|
||||
- }
|
||||
si_read_unlock(sb);
|
||||
kfree(a);
|
||||
out:
|
||||
@@ -812,6 +805,16 @@ static int aufs_setattr(struct dentry *d
|
||||
return err;
|
||||
}
|
||||
|
||||
+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
|
||||
+{
|
||||
+ return aufs_do_setattr(dentry, ia, NULL);
|
||||
+}
|
||||
+
|
||||
+int aufs_fsetattr(struct file *file, struct iattr *ia)
|
||||
+{
|
||||
+ return aufs_do_setattr(file->f_dentry, ia, file);
|
||||
+}
|
||||
+
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
|
||||
--- a/fs/aufs25/inode.h
|
||||
+++ b/fs/aufs25/inode.h
|
||||
@@ -84,6 +84,7 @@ int au_test_h_perm_sio(struct inode *h_i
|
||||
|
||||
/* i_op.c */
|
||||
extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
|
||||
+int aufs_fsetattr(struct file *file, struct iattr *ia);
|
||||
|
||||
/* au_wr_dir flags */
|
||||
#define AuWrDir_ADD_ENTRY 1
|
||||
--- a/fs/aufs25/misc.c
|
||||
+++ b/fs/aufs25/misc.c
|
||||
@@ -267,13 +267,12 @@ int au_copy_file(struct file *dst, struc
|
||||
if (err == 1) {
|
||||
ia = (void *)buf;
|
||||
ia->ia_size = dst->f_pos;
|
||||
- ia->ia_valid = ATTR_SIZE | ATTR_FILE;
|
||||
- ia->ia_file = dst;
|
||||
+ ia->ia_valid = ATTR_SIZE;
|
||||
vfsub_args_reinit(vargs);
|
||||
vfsub_ign_hinode(vargs, vfsub_events_notify_change(ia),
|
||||
hdir);
|
||||
mutex_lock_nested(&h_i->i_mutex, AuLsc_I_CHILD2);
|
||||
- err = vfsub_notify_change(h_d, ia, vargs);
|
||||
+ err = vfsub_fnotify_change(h_d, ia, vargs, dst);
|
||||
mutex_unlock(&h_i->i_mutex);
|
||||
}
|
||||
}
|
||||
--- a/fs/aufs25/vfsub.c
|
||||
+++ b/fs/aufs25/vfsub.c
|
||||
@@ -477,6 +477,7 @@ struct notify_change_args {
|
||||
struct dentry *h_dentry;
|
||||
struct iattr *ia;
|
||||
struct vfsub_args *vargs;
|
||||
+ struct file *file;
|
||||
};
|
||||
|
||||
static void call_notify_change(void *args)
|
||||
@@ -493,7 +494,7 @@ static void call_notify_change(void *arg
|
||||
if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
|
||||
vfsub_ignore(a->vargs);
|
||||
lockdep_off();
|
||||
- *a->errp = notify_change(a->h_dentry, NULL, a->ia);
|
||||
+ *a->errp = fnotify_change(a->h_dentry, NULL, a->ia, a->file);
|
||||
lockdep_on();
|
||||
if (!*a->errp)
|
||||
au_update_fuse_h_inode(NULL, a->h_dentry); /*ignore*/
|
||||
@@ -525,8 +526,8 @@ static void vfsub_notify_change_dlgt(str
|
||||
}
|
||||
#endif
|
||||
|
||||
-int vfsub_notify_change(struct dentry *dentry, struct iattr *ia,
|
||||
- struct vfsub_args *vargs)
|
||||
+int vfsub_fnotify_change(struct dentry *dentry, struct iattr *ia,
|
||||
+ struct vfsub_args *vargs, struct file *file)
|
||||
{
|
||||
int err;
|
||||
struct notify_change_args args = {
|
||||
@@ -570,6 +571,12 @@ int vfsub_sio_notify_change(struct au_hi
|
||||
return err;
|
||||
}
|
||||
|
||||
+int vfsub_notify_change(struct dentry *dentry, struct iattr *ia,
|
||||
+ struct vfsub_args *vargs)
|
||||
+{
|
||||
+ return vfsub_fnotify_change(dentry, ia, vargs, NULL);
|
||||
+}
|
||||
+
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
struct unlink_args {
|
||||
--- a/fs/aufs25/vfsub.h
|
||||
+++ b/fs/aufs25/vfsub.h
|
||||
@@ -508,6 +508,8 @@ int vfsub_sio_notify_change(struct au_hi
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
+int vfsub_fnotify_change(struct dentry *dentry, struct iattr *ia,
|
||||
+ struct vfsub_args *vargs, struct file *file);
|
||||
int vfsub_notify_change(struct dentry *dentry, struct iattr *ia,
|
||||
struct vfsub_args *vargs);
|
||||
int vfsub_unlink(struct inode *dir, struct dentry *dentry,
|
60
kernel-patches/2.6.28/d_namespace_path.diff
Normal file
60
kernel-patches/2.6.28/d_namespace_path.diff
Normal file
|
@ -0,0 +1,60 @@
|
|||
From: Andreas Gruenbacher <agruen@suse.de>
|
||||
Subject: Add d_namespace_path() to compute namespace relative pathnames
|
||||
|
||||
In AppArmor, we are interested in pathnames relative to the namespace root.
|
||||
This is the same as d_path() except for the root where the search ends. Add
|
||||
a function for computing the namespace-relative path.
|
||||
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/namespace.c | 30 ++++++++++++++++++++++++++++++
|
||||
include/linux/mount.h | 2 ++
|
||||
2 files changed, 32 insertions(+)
|
||||
|
||||
--- a/fs/namespace.c
|
||||
+++ b/fs/namespace.c
|
||||
@@ -2349,3 +2349,33 @@ void __put_mnt_ns(struct mnt_namespace *
|
||||
release_mounts(&umount_list);
|
||||
kfree(ns);
|
||||
}
|
||||
+
|
||||
+char *d_namespace_path(struct dentry *dentry, struct vfsmount *vfsmnt,
|
||||
+ char *buf, int buflen)
|
||||
+{
|
||||
+ struct path root, tmp, ns_root = { };
|
||||
+ struct path path = { .mnt = vfsmnt, .dentry = dentry };
|
||||
+ char *res;
|
||||
+
|
||||
+ read_lock(¤t->fs->lock);
|
||||
+ root = current->fs->root;
|
||||
+ path_get(¤t->fs->root);
|
||||
+ read_unlock(¤t->fs->lock);
|
||||
+ spin_lock(&vfsmount_lock);
|
||||
+ if (root.mnt)
|
||||
+ ns_root.mnt = mntget(root.mnt->mnt_ns->root);
|
||||
+ if (ns_root.mnt)
|
||||
+ ns_root.dentry = dget(ns_root.mnt->mnt_root);
|
||||
+ spin_unlock(&vfsmount_lock);
|
||||
+ tmp = ns_root;
|
||||
+ res = __d_path(&path, &tmp, buf, buflen,
|
||||
+ D_PATH_FAIL_DELETED | D_PATH_DISCONNECT);
|
||||
+ path_put(&root);
|
||||
+ path_put(&ns_root);
|
||||
+
|
||||
+ /* Prevent empty path for lazily unmounted filesystems. */
|
||||
+ if (!IS_ERR(res) && *res == '\0')
|
||||
+ *--res = '.';
|
||||
+ return res;
|
||||
+}
|
||||
+EXPORT_SYMBOL(d_namespace_path);
|
||||
--- a/include/linux/mount.h
|
||||
+++ b/include/linux/mount.h
|
||||
@@ -112,4 +112,6 @@ extern void mark_mounts_for_expiry(struc
|
||||
extern spinlock_t vfsmount_lock;
|
||||
extern dev_t name_to_dev_t(char *name);
|
||||
|
||||
+extern char *d_namespace_path(struct dentry *, struct vfsmount *, char *, int);
|
||||
+
|
||||
#endif /* _LINUX_MOUNT_H */
|
42
kernel-patches/2.6.28/do_path_lookup-nameidata.diff
Normal file
42
kernel-patches/2.6.28/do_path_lookup-nameidata.diff
Normal file
|
@ -0,0 +1,42 @@
|
|||
From: Andreas Gruenbacher <agruen@suse.de>
|
||||
Subject: Switch to vfs_permission() in do_path_lookup()
|
||||
|
||||
Switch from file_permission() to vfs_permission() in do_path_lookup():
|
||||
this avoids calling permission() with a NULL nameidata here.
|
||||
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/namei.c | 7 ++-----
|
||||
1 file changed, 2 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -1067,24 +1067,21 @@ static int do_path_lookup(int dfd, const
|
||||
path_get(&fs->pwd);
|
||||
read_unlock(&fs->lock);
|
||||
} else {
|
||||
- struct dentry *dentry;
|
||||
-
|
||||
file = fget_light(dfd, &fput_needed);
|
||||
retval = -EBADF;
|
||||
if (!file)
|
||||
goto out_fail;
|
||||
|
||||
- dentry = file->f_path.dentry;
|
||||
+ nd->path = file->f_path;
|
||||
|
||||
retval = -ENOTDIR;
|
||||
- if (!S_ISDIR(dentry->d_inode->i_mode))
|
||||
+ if (!S_ISDIR(nd->path.dentry->d_inode->i_mode))
|
||||
goto fput_fail;
|
||||
|
||||
retval = file_permission(file, MAY_EXEC);
|
||||
if (retval)
|
||||
goto fput_fail;
|
||||
|
||||
- nd->path = file->f_path;
|
||||
path_get(&file->f_path);
|
||||
|
||||
fput_light(file, fput_needed);
|
|
@ -0,0 +1,26 @@
|
|||
From: Jeff Mahoney <jeffm@suse.com>
|
||||
Subject: [PATCH] LSM: Export security_inode_permission for aufs
|
||||
Patch-mainline: Never
|
||||
References: 356902
|
||||
|
||||
In order for aufs to work with AppArmor, it needs to be able to call
|
||||
security_inode_permission itself.
|
||||
|
||||
This patch is a _workaround_ since the author will need to find a
|
||||
mainline-compatible solution moving forward.
|
||||
|
||||
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
security/security.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -424,6 +424,7 @@ int security_inode_mknod(struct inode *d
|
||||
return 0;
|
||||
return security_ops->inode_mknod(dir, dentry, mnt, mode, dev);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(security_inode_permission);
|
||||
|
||||
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
struct vfsmount *old_mnt, struct inode *new_dir,
|
84
kernel-patches/2.6.28/file-handle-ops.diff
Normal file
84
kernel-patches/2.6.28/file-handle-ops.diff
Normal file
|
@ -0,0 +1,84 @@
|
|||
From: Andreas Gruenbacher <agruen@suse.de>
|
||||
Subject: Enable LSM hooks to distinguish operations on file descriptors from operations on pathnames
|
||||
|
||||
Struct iattr already contains ia_file since commit cc4e69de from
|
||||
Miklos (which is related to commit befc649c). Use this to pass
|
||||
struct file down the setattr hooks. This allows LSMs to distinguish
|
||||
operations on file descriptors from operations on paths.
|
||||
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
Cc: Miklos Szeredi <mszeredi@suse.cz>
|
||||
|
||||
---
|
||||
fs/nfsd/vfs.c | 12 +++++++-----
|
||||
fs/open.c | 5 ++++-
|
||||
2 files changed, 11 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/fs/nfsd/vfs.c
|
||||
+++ b/fs/nfsd/vfs.c
|
||||
@@ -413,7 +413,7 @@ static ssize_t nfsd_getxattr(struct dent
|
||||
ssize_t buflen;
|
||||
ssize_t ret;
|
||||
|
||||
- buflen = vfs_getxattr(dentry, mnt, key, NULL, 0);
|
||||
+ buflen = vfs_getxattr(dentry, mnt, key, NULL, 0, NULL);
|
||||
if (buflen <= 0)
|
||||
return buflen;
|
||||
|
||||
@@ -421,7 +421,7 @@ static ssize_t nfsd_getxattr(struct dent
|
||||
if (!*buf)
|
||||
return -ENOMEM;
|
||||
|
||||
- ret = vfs_getxattr(dentry, mnt, key, *buf, buflen);
|
||||
+ ret = vfs_getxattr(dentry, mnt, key, *buf, buflen, NULL);
|
||||
if (ret < 0)
|
||||
kfree(*buf);
|
||||
return ret;
|
||||
@@ -450,7 +450,7 @@ set_nfsv4_acl_one(struct dentry *dentry,
|
||||
goto out;
|
||||
}
|
||||
|
||||
- error = vfs_setxattr(dentry, mnt, key, buf, len, 0);
|
||||
+ error = vfs_setxattr(dentry, mnt, key, buf, len, 0, NULL);
|
||||
out:
|
||||
kfree(buf);
|
||||
return error;
|
||||
@@ -2212,12 +2212,14 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
|
||||
if (error)
|
||||
goto getout;
|
||||
if (size)
|
||||
- error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size,0);
|
||||
+ error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size, 0,
|
||||
+ NULL);
|
||||
else {
|
||||
if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
|
||||
error = 0;
|
||||
else {
|
||||
- error = vfs_removexattr(fhp->fh_dentry, mnt, name);
|
||||
+ error = vfs_removexattr(fhp->fh_dentry, mnt, name,
|
||||
+ NULL);
|
||||
if (error == -ENODATA)
|
||||
error = 0;
|
||||
}
|
||||
--- a/fs/open.c
|
||||
+++ b/fs/open.c
|
||||
@@ -604,7 +604,7 @@ asmlinkage long sys_fchmod(unsigned int
|
||||
if (mode == (mode_t) -1)
|
||||
mode = inode->i_mode;
|
||||
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
|
||||
- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
|
||||
+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME | ATTR_FILE;
|
||||
err = fnotify_change(dentry, file->f_path.mnt, &newattrs, file);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
mnt_drop_write(file->f_path.mnt);
|
||||
@@ -668,6 +668,9 @@ static int chown_common(struct dentry *
|
||||
if (!S_ISDIR(inode->i_mode))
|
||||
newattrs.ia_valid |=
|
||||
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
|
||||
+ if (file)
|
||||
+ newattrs.ia_valid |= ATTR_FILE;
|
||||
+
|
||||
mutex_lock(&inode->i_mutex);
|
||||
error = fnotify_change(dentry, mnt, &newattrs, file);
|
||||
mutex_unlock(&inode->i_mutex);
|
26
kernel-patches/2.6.28/fix-complain.diff
Normal file
26
kernel-patches/2.6.28/fix-complain.diff
Normal file
|
@ -0,0 +1,26 @@
|
|||
From: John Johansen <jjohansen@suse.de>
|
||||
Subject: fix enforcement of deny rules in complain mode
|
||||
Patch-mainline: no
|
||||
References: bnc#426159
|
||||
|
||||
Fix enforcement of deny rules so that they are not enforced in complain
|
||||
mode. This is necessary so that application behavior is not changed by
|
||||
the presence of the deny rule.
|
||||
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
security/apparmor/main.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/security/apparmor/main.c
|
||||
+++ b/security/apparmor/main.c
|
||||
@@ -325,7 +325,7 @@ static int aa_audit_file(struct aa_profi
|
||||
} else {
|
||||
int mask = AUDIT_QUIET_MASK(sa->audit_mask);
|
||||
|
||||
- if (!(sa->denied_mask & ~mask))
|
||||
+ if (!(sa->denied_mask & ~mask) && !PROFILE_COMPLAIN(profile))
|
||||
return sa->error_code;
|
||||
|
||||
/* mask off perms whose denial is being silenced */
|
14
kernel-patches/2.6.28/fix-config.diff
Normal file
14
kernel-patches/2.6.28/fix-config.diff
Normal file
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
security/apparmor/Kconfig | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/security/apparmor/Kconfig
|
||||
+++ b/security/apparmor/Kconfig
|
||||
@@ -1,6 +1,7 @@
|
||||
config SECURITY_APPARMOR
|
||||
bool "AppArmor support"
|
||||
depends on SECURITY
|
||||
+ depends on SECURITY_NETWORK
|
||||
select AUDIT
|
||||
help
|
||||
This enables the AppArmor security module.
|
15
kernel-patches/2.6.28/fix-d_namespace_path.diff
Normal file
15
kernel-patches/2.6.28/fix-d_namespace_path.diff
Normal file
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
fs/namespace.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/fs/namespace.c
|
||||
+++ b/fs/namespace.c
|
||||
@@ -2362,7 +2362,7 @@ char *d_namespace_path(struct dentry *de
|
||||
path_get(¤t->fs->root);
|
||||
read_unlock(¤t->fs->lock);
|
||||
spin_lock(&vfsmount_lock);
|
||||
- if (root.mnt)
|
||||
+ if (root.mnt && root.mnt->mnt_ns)
|
||||
ns_root.mnt = mntget(root.mnt->mnt_ns->root);
|
||||
if (ns_root.mnt)
|
||||
ns_root.dentry = dget(ns_root.mnt->mnt_root);
|
35
kernel-patches/2.6.28/fix-security-param.diff
Normal file
35
kernel-patches/2.6.28/fix-security-param.diff
Normal file
|
@ -0,0 +1,35 @@
|
|||
From: John Johansen <jjohansen@suse.de>
|
||||
Subject: fix recognition of security= boot parameter
|
||||
Patch-mainline: no
|
||||
References: bnc#442668
|
||||
|
||||
Fix AppArmor to respect the kernel boot parameter security=, so that if a
|
||||
different lsm is choosen apparmor does not try to register its lsm hooks.
|
||||
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
security/apparmor/lsm.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -911,6 +911,7 @@ static int apparmor_task_setrlimit(unsig
|
||||
}
|
||||
|
||||
struct security_operations apparmor_ops = {
|
||||
+ .name = "apparmor",
|
||||
.ptrace_may_access = apparmor_ptrace_may_access,
|
||||
.ptrace_traceme = apparmor_ptrace_traceme,
|
||||
.capget = cap_capget,
|
||||
@@ -989,8 +990,8 @@ static int __init apparmor_init(void)
|
||||
{
|
||||
int error;
|
||||
|
||||
- if (!apparmor_enabled) {
|
||||
- info_message("AppArmor disabled by boottime parameter\n");
|
||||
+ if (!apparmor_enabled || !security_module_enable(&apparmor_ops)) {
|
||||
+ info_message("AppArmor disabled by boot time parameter\n");
|
||||
return 0;
|
||||
}
|
||||
|
44
kernel-patches/2.6.28/fix-vfs_rmdir.diff
Normal file
44
kernel-patches/2.6.28/fix-vfs_rmdir.diff
Normal file
|
@ -0,0 +1,44 @@
|
|||
From: John Johansen <jjohansen@suse.de>
|
||||
Subject: Call lsm hook before unhashing dentry in vfs_rmdir()
|
||||
|
||||
If we unhash the dentry before calling the security_inode_rmdir hook,
|
||||
we cannot compute the file's pathname in the hook anymore. AppArmor
|
||||
needs to know the filename in order to decide whether a file may be
|
||||
deleted, though.
|
||||
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
|
||||
---
|
||||
fs/namei.c | 13 +++++++------
|
||||
1 file changed, 7 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -2125,6 +2125,10 @@ int vfs_rmdir(struct inode *dir, struct
|
||||
if (!dir->i_op || !dir->i_op->rmdir)
|
||||
return -EPERM;
|
||||
|
||||
+ error = security_inode_rmdir(dir, dentry, mnt);
|
||||
+ if (error)
|
||||
+ return error;
|
||||
+
|
||||
DQUOT_INIT(dir);
|
||||
|
||||
mutex_lock(&dentry->d_inode->i_mutex);
|
||||
@@ -2132,12 +2136,9 @@ int vfs_rmdir(struct inode *dir, struct
|
||||
if (d_mountpoint(dentry))
|
||||
error = -EBUSY;
|
||||
else {
|
||||
- error = security_inode_rmdir(dir, dentry, mnt);
|
||||
- if (!error) {
|
||||
- error = dir->i_op->rmdir(dir, dentry);
|
||||
- if (!error)
|
||||
- dentry->d_inode->i_flags |= S_DEAD;
|
||||
- }
|
||||
+ error = dir->i_op->rmdir(dir, dentry);
|
||||
+ if (!error)
|
||||
+ dentry->d_inode->i_flags |= S_DEAD;
|
||||
}
|
||||
mutex_unlock(&dentry->d_inode->i_mutex);
|
||||
if (!error) {
|
56
kernel-patches/2.6.28/fork-tracking.diff
Normal file
56
kernel-patches/2.6.28/fork-tracking.diff
Normal file
|
@ -0,0 +1,56 @@
|
|||
From: John Johansen <jjohansen@suse.de>
|
||||
Subject: fix log messages to enable tools profile learning
|
||||
Patch-mainline: no
|
||||
References: bnc#447564
|
||||
|
||||
The allocation of the child pid is done after the LSM clone hook, which
|
||||
breaks the AppArmor tools fork tracking, for profiles learning. Output
|
||||
the parent pid with each log message to enable the tools to handle fork
|
||||
tracking.
|
||||
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
security/apparmor/main.c | 10 +++++-----
|
||||
security/apparmor/module_interface.c | 2 +-
|
||||
2 files changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/security/apparmor/main.c
|
||||
+++ b/security/apparmor/main.c
|
||||
@@ -229,9 +229,13 @@ static int aa_audit_base(struct aa_profi
|
||||
audit_log_format(ab, " protocol=%d", sa->protocol);
|
||||
}
|
||||
|
||||
- audit_log_format(ab, " pid=%d", current->pid);
|
||||
+ audit_log_format(ab, " pid=%d", current->pid);
|
||||
|
||||
if (profile) {
|
||||
+ if (!sa->parent)
|
||||
+ audit_log_format(ab, " parent=%d",
|
||||
+ current->real_parent->pid);
|
||||
+
|
||||
audit_log_format(ab, " profile=");
|
||||
audit_log_untrustedstring(ab, profile->name);
|
||||
|
||||
@@ -1007,10 +1011,6 @@ repeat:
|
||||
|
||||
unlock_profile(profile);
|
||||
|
||||
- if (APPARMOR_COMPLAIN(child_cxt) &&
|
||||
- profile == profile->ns->null_complain_profile) {
|
||||
- aa_audit_hint(profile, &sa);
|
||||
- }
|
||||
aa_put_profile(profile);
|
||||
} else
|
||||
aa_free_task_context(child_cxt);
|
||||
--- a/security/apparmor/module_interface.c
|
||||
+++ b/security/apparmor/module_interface.c
|
||||
@@ -126,7 +126,7 @@ static int aa_is_nameX(struct aa_ext *e,
|
||||
* AA_NAME tag value is a u16.
|
||||
*/
|
||||
if (aa_is_X(e, AA_NAME)) {
|
||||
- char *tag;
|
||||
+ char *tag = NULL;
|
||||
size_t size = aa_is_u16_chunk(e, &tag);
|
||||
/* if a name is specified it must match. otherwise skip tag */
|
||||
if (name && (!size || strcmp(name, tag)))
|
28
kernel-patches/2.6.28/fsetattr-reintro-ATTR_FILE.diff
Normal file
28
kernel-patches/2.6.28/fsetattr-reintro-ATTR_FILE.diff
Normal file
|
@ -0,0 +1,28 @@
|
|||
From: John Johansen <jjohansen@suse.de>
|
||||
Subject: AppArmor: reintroduce ATTR_FILE
|
||||
|
||||
The fsetattr patch removed ATTR_FILE but AppArmor needs it to distinguish
|
||||
file based writes.
|
||||
|
||||
Note: Now that LSMs must be static, it would be better to add a file
|
||||
pointer argument to security_operations->inode_setattr() instead. Then
|
||||
move the fs.h chunk to patches.apparmor/fsetattr-restore-ia_file. -jeffm
|
||||
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/open.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
--- a/fs/open.c
|
||||
+++ b/fs/open.c
|
||||
@@ -210,6 +210,9 @@ int do_truncate(struct dentry *dentry, s
|
||||
newattrs.ia_size = length;
|
||||
newattrs.ia_valid = ATTR_SIZE | time_attrs;
|
||||
|
||||
+ if (filp)
|
||||
+ newattrs.ia_valid |= ATTR_FILE;
|
||||
+
|
||||
/* Remove suid/sgid on truncate too */
|
||||
newattrs.ia_valid |= should_remove_suid(dentry);
|
||||
|
61
kernel-patches/2.6.28/fsetattr-restore-ia_file.diff
Normal file
61
kernel-patches/2.6.28/fsetattr-restore-ia_file.diff
Normal file
|
@ -0,0 +1,61 @@
|
|||
From: Jeff Mahoney <jeffm@suse.com>
|
||||
Subject: [PATCH] vfs: restore ia_file for compatibility with external modules
|
||||
References: bnc#381259
|
||||
|
||||
patches.apparmor/fsetattr.diff eliminated ia_file and ATTR_FILE in favor
|
||||
of providing a ->fsetattr call that used a file pointer. Until this
|
||||
patch is accepted into mainline, this patch provides the backward
|
||||
compatibility for external file system modules.
|
||||
|
||||
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
|
||||
---
|
||||
fs/attr.c | 15 +++++++++++++--
|
||||
include/linux/fs.h | 11 +++++++++++
|
||||
2 files changed, 24 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/fs/attr.c
|
||||
+++ b/fs/attr.c
|
||||
@@ -168,10 +168,21 @@ int fnotify_change(struct dentry *dentry
|
||||
down_write(&dentry->d_inode->i_alloc_sem);
|
||||
|
||||
if (inode->i_op && inode->i_op->setattr) {
|
||||
- if (file && file->f_op && file->f_op->fsetattr)
|
||||
+ if (file && file->f_op && file->f_op->fsetattr) {
|
||||
error = file->f_op->fsetattr(file, attr);
|
||||
- else
|
||||
+ } else {
|
||||
+ /* External file system still expect to be
|
||||
+ * passed a file pointer via ia_file and
|
||||
+ * have it announced via ATTR_FILE. This
|
||||
+ * just makes it so they don't need to
|
||||
+ * change their API just for us. External
|
||||
+ * callers will have set these themselves. */
|
||||
+ if (file) {
|
||||
+ attr->ia_valid |= ATTR_FILE;
|
||||
+ attr->ia_file = file;
|
||||
+ }
|
||||
error = inode->i_op->setattr(dentry, attr);
|
||||
+ }
|
||||
} else {
|
||||
error = inode_change_ok(inode, attr);
|
||||
if (!error) {
|
||||
--- a/include/linux/fs.h
|
||||
+++ b/include/linux/fs.h
|
||||
@@ -367,6 +367,17 @@ struct iattr {
|
||||
struct timespec ia_atime;
|
||||
struct timespec ia_mtime;
|
||||
struct timespec ia_ctime;
|
||||
+
|
||||
+ /*
|
||||
+ * Not an attribute, but an auxilary info for filesystems wanting to
|
||||
+ * implement an ftruncate() like method. NOTE: filesystem should
|
||||
+ * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL).
|
||||
+ *
|
||||
+ * NOTE: With patches.apparmor/fsetattr.diff applied, this is
|
||||
+ * for compatibility with external file system modules only. There
|
||||
+ * should not be any in-kernel users left.
|
||||
+ */
|
||||
+ struct file *ia_file;
|
||||
};
|
||||
|
||||
/*
|
411
kernel-patches/2.6.28/fsetattr.diff
Normal file
411
kernel-patches/2.6.28/fsetattr.diff
Normal file
|
@ -0,0 +1,411 @@
|
|||
Subject: VFS: new fsetattr() file operation
|
||||
|
||||
From: Miklos Szeredi <mszeredi@suse.cz>
|
||||
|
||||
Add a new file operation: f_op->fsetattr(), that is invoked by
|
||||
ftruncate, fchmod, fchown and utimensat. Fall back to i_op->setattr()
|
||||
if it is not defined.
|
||||
|
||||
For the reasons why we need this, see patch adding fgetattr().
|
||||
|
||||
ftruncate() already passed the open file to the filesystem via the
|
||||
ia_file member of struct iattr. However it is cleaner to have a
|
||||
separate file operation for this, so remove ia_file, ATTR_FILE and
|
||||
convert existing users: fuse and AFS.
|
||||
|
||||
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> ---
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de> ---
|
||||
|
||||
---
|
||||
fs/afs/dir.c | 1 +
|
||||
fs/afs/file.c | 1 +
|
||||
fs/afs/inode.c | 19 +++++++++++++++----
|
||||
fs/afs/internal.h | 1 +
|
||||
fs/attr.c | 16 +++++++++++++---
|
||||
fs/fuse/dir.c | 20 +++++++++-----------
|
||||
fs/fuse/file.c | 7 +++++++
|
||||
fs/fuse/fuse_i.h | 4 ++++
|
||||
fs/open.c | 20 ++++++++------------
|
||||
fs/utimes.c | 9 +++++----
|
||||
include/linux/fs.h | 9 ++-------
|
||||
11 files changed, 66 insertions(+), 41 deletions(-)
|
||||
|
||||
--- a/fs/afs/dir.c
|
||||
+++ b/fs/afs/dir.c
|
||||
@@ -46,6 +46,7 @@ const struct file_operations afs_dir_fil
|
||||
.readdir = afs_readdir,
|
||||
.lock = afs_lock,
|
||||
.llseek = generic_file_llseek,
|
||||
+ .fsetattr = afs_fsetattr,
|
||||
};
|
||||
|
||||
const struct inode_operations afs_dir_inode_operations = {
|
||||
--- a/fs/afs/file.c
|
||||
+++ b/fs/afs/file.c
|
||||
@@ -36,6 +36,7 @@ const struct file_operations afs_file_op
|
||||
.fsync = afs_fsync,
|
||||
.lock = afs_lock,
|
||||
.flock = afs_flock,
|
||||
+ .fsetattr = afs_fsetattr,
|
||||
};
|
||||
|
||||
const struct inode_operations afs_file_inode_operations = {
|
||||
--- a/fs/afs/inode.c
|
||||
+++ b/fs/afs/inode.c
|
||||
@@ -358,7 +358,8 @@ void afs_clear_inode(struct inode *inode
|
||||
/*
|
||||
* set the attributes of an inode
|
||||
*/
|
||||
-int afs_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
+static int afs_do_setattr(struct dentry *dentry, struct iattr *attr,
|
||||
+ struct file *file)
|
||||
{
|
||||
struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
|
||||
struct key *key;
|
||||
@@ -380,8 +381,8 @@ int afs_setattr(struct dentry *dentry, s
|
||||
afs_writeback_all(vnode);
|
||||
}
|
||||
|
||||
- if (attr->ia_valid & ATTR_FILE) {
|
||||
- key = attr->ia_file->private_data;
|
||||
+ if (file) {
|
||||
+ key = file->private_data;
|
||||
} else {
|
||||
key = afs_request_key(vnode->volume->cell);
|
||||
if (IS_ERR(key)) {
|
||||
@@ -391,10 +392,20 @@ int afs_setattr(struct dentry *dentry, s
|
||||
}
|
||||
|
||||
ret = afs_vnode_setattr(vnode, key, attr);
|
||||
- if (!(attr->ia_valid & ATTR_FILE))
|
||||
+ if (!file)
|
||||
key_put(key);
|
||||
|
||||
error:
|
||||
_leave(" = %d", ret);
|
||||
return ret;
|
||||
}
|
||||
+
|
||||
+int afs_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
+{
|
||||
+ return afs_do_setattr(dentry, attr, NULL);
|
||||
+}
|
||||
+
|
||||
+int afs_fsetattr(struct file *file, struct iattr *attr)
|
||||
+{
|
||||
+ return afs_do_setattr(file->f_path.dentry, attr, file);
|
||||
+}
|
||||
--- a/fs/afs/internal.h
|
||||
+++ b/fs/afs/internal.h
|
||||
@@ -548,6 +548,7 @@ extern void afs_zap_data(struct afs_vnod
|
||||
extern int afs_validate(struct afs_vnode *, struct key *);
|
||||
extern int afs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
|
||||
extern int afs_setattr(struct dentry *, struct iattr *);
|
||||
+extern int afs_fsetattr(struct file *, struct iattr *);
|
||||
extern void afs_clear_inode(struct inode *);
|
||||
|
||||
/*
|
||||
--- a/fs/attr.c
|
||||
+++ b/fs/attr.c
|
||||
@@ -100,8 +100,8 @@ int inode_setattr(struct inode * inode,
|
||||
}
|
||||
EXPORT_SYMBOL(inode_setattr);
|
||||
|
||||
-int notify_change(struct dentry *dentry, struct vfsmount *mnt,
|
||||
- struct iattr *attr)
|
||||
+int fnotify_change(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ struct iattr *attr, struct file *file)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
mode_t mode = inode->i_mode;
|
||||
@@ -168,7 +168,10 @@ int notify_change(struct dentry *dentry,
|
||||
down_write(&dentry->d_inode->i_alloc_sem);
|
||||
|
||||
if (inode->i_op && inode->i_op->setattr) {
|
||||
- error = inode->i_op->setattr(dentry, attr);
|
||||
+ if (file && file->f_op && file->f_op->fsetattr)
|
||||
+ error = file->f_op->fsetattr(file, attr);
|
||||
+ else
|
||||
+ error = inode->i_op->setattr(dentry, attr);
|
||||
} else {
|
||||
error = inode_change_ok(inode, attr);
|
||||
if (!error) {
|
||||
@@ -188,5 +191,12 @@ int notify_change(struct dentry *dentry,
|
||||
|
||||
return error;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(fnotify_change);
|
||||
+
|
||||
+int notify_change(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ struct iattr *attr)
|
||||
+{
|
||||
+ return fnotify_change(dentry, mnt, attr, NULL);
|
||||
+}
|
||||
|
||||
EXPORT_SYMBOL(notify_change);
|
||||
--- a/fs/fuse/dir.c
|
||||
+++ b/fs/fuse/dir.c
|
||||
@@ -1105,21 +1105,22 @@ static int fuse_dir_fsync(struct file *f
|
||||
return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
|
||||
}
|
||||
|
||||
-static bool update_mtime(unsigned ivalid)
|
||||
+static bool update_mtime(unsigned ivalid, bool have_file)
|
||||
{
|
||||
/* Always update if mtime is explicitly set */
|
||||
if (ivalid & ATTR_MTIME_SET)
|
||||
return true;
|
||||
|
||||
/* If it's an open(O_TRUNC) or an ftruncate(), don't update */
|
||||
- if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
|
||||
+ if ((ivalid & ATTR_SIZE) && ((ivalid & ATTR_OPEN) || have_file))
|
||||
return false;
|
||||
|
||||
/* In all other cases update */
|
||||
return true;
|
||||
}
|
||||
|
||||
-static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
|
||||
+static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
|
||||
+ bool have_file)
|
||||
{
|
||||
unsigned ivalid = iattr->ia_valid;
|
||||
|
||||
@@ -1138,7 +1139,7 @@ static void iattr_to_fattr(struct iattr
|
||||
if (!(ivalid & ATTR_ATIME_SET))
|
||||
arg->valid |= FATTR_ATIME_NOW;
|
||||
}
|
||||
- if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
|
||||
+ if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, have_file)) {
|
||||
arg->valid |= FATTR_MTIME;
|
||||
arg->mtime = iattr->ia_mtime.tv_sec;
|
||||
arg->mtimensec = iattr->ia_mtime.tv_nsec;
|
||||
@@ -1199,8 +1200,8 @@ void fuse_release_nowrite(struct inode *
|
||||
* vmtruncate() doesn't allow for this case, so do the rlimit checking
|
||||
* and the actual truncation by hand.
|
||||
*/
|
||||
-static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
|
||||
- struct file *file)
|
||||
+int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
|
||||
+ struct file *file)
|
||||
{
|
||||
struct inode *inode = entry->d_inode;
|
||||
struct fuse_conn *fc = get_fuse_conn(inode);
|
||||
@@ -1244,7 +1245,7 @@ static int fuse_do_setattr(struct dentry
|
||||
|
||||
memset(&inarg, 0, sizeof(inarg));
|
||||
memset(&outarg, 0, sizeof(outarg));
|
||||
- iattr_to_fattr(attr, &inarg);
|
||||
+ iattr_to_fattr(attr, &inarg, file != NULL);
|
||||
if (file) {
|
||||
struct fuse_file *ff = file->private_data;
|
||||
inarg.valid |= FATTR_FH;
|
||||
@@ -1314,10 +1315,7 @@ error:
|
||||
|
||||
static int fuse_setattr(struct dentry *entry, struct iattr *attr)
|
||||
{
|
||||
- if (attr->ia_valid & ATTR_FILE)
|
||||
- return fuse_do_setattr(entry, attr, attr->ia_file);
|
||||
- else
|
||||
- return fuse_do_setattr(entry, attr, NULL);
|
||||
+ return fuse_do_setattr(entry, attr, NULL);
|
||||
}
|
||||
|
||||
static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
|
||||
--- a/fs/fuse/file.c
|
||||
+++ b/fs/fuse/file.c
|
||||
@@ -1470,6 +1470,11 @@ static loff_t fuse_file_llseek(struct fi
|
||||
return retval;
|
||||
}
|
||||
|
||||
+static int fuse_fsetattr(struct file *file, struct iattr *attr)
|
||||
+{
|
||||
+ return fuse_do_setattr(file->f_path.dentry, attr, file);
|
||||
+}
|
||||
+
|
||||
static const struct file_operations fuse_file_operations = {
|
||||
.llseek = fuse_file_llseek,
|
||||
.read = do_sync_read,
|
||||
@@ -1483,6 +1488,7 @@ static const struct file_operations fuse
|
||||
.fsync = fuse_fsync,
|
||||
.lock = fuse_file_lock,
|
||||
.flock = fuse_file_flock,
|
||||
+ .fsetattr = fuse_fsetattr,
|
||||
.splice_read = generic_file_splice_read,
|
||||
};
|
||||
|
||||
@@ -1496,6 +1502,7 @@ static const struct file_operations fuse
|
||||
.fsync = fuse_fsync,
|
||||
.lock = fuse_file_lock,
|
||||
.flock = fuse_file_flock,
|
||||
+ .fsetattr = fuse_fsetattr,
|
||||
/* no mmap and splice_read */
|
||||
};
|
||||
|
||||
--- a/fs/fuse/fuse_i.h
|
||||
+++ b/fs/fuse/fuse_i.h
|
||||
@@ -554,6 +554,10 @@ void fuse_truncate(struct address_space
|
||||
*/
|
||||
int fuse_dev_init(void);
|
||||
|
||||
+
|
||||
+int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
|
||||
+ struct file *file);
|
||||
+
|
||||
/**
|
||||
* Cleanup the client device
|
||||
*/
|
||||
--- a/fs/open.c
|
||||
+++ b/fs/open.c
|
||||
@@ -209,16 +209,12 @@ int do_truncate(struct dentry *dentry, s
|
||||
|
||||
newattrs.ia_size = length;
|
||||
newattrs.ia_valid = ATTR_SIZE | time_attrs;
|
||||
- if (filp) {
|
||||
- newattrs.ia_file = filp;
|
||||
- newattrs.ia_valid |= ATTR_FILE;
|
||||
- }
|
||||
|
||||
/* Remove suid/sgid on truncate too */
|
||||
newattrs.ia_valid |= should_remove_suid(dentry);
|
||||
|
||||
mutex_lock(&dentry->d_inode->i_mutex);
|
||||
- err = notify_change(dentry, mnt, &newattrs);
|
||||
+ err = fnotify_change(dentry, mnt, &newattrs, filp);
|
||||
mutex_unlock(&dentry->d_inode->i_mutex);
|
||||
return err;
|
||||
}
|
||||
@@ -606,7 +602,7 @@ asmlinkage long sys_fchmod(unsigned int
|
||||
mode = inode->i_mode;
|
||||
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
|
||||
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
|
||||
- err = notify_change(dentry, file->f_path.mnt, &newattrs);
|
||||
+ err = fnotify_change(dentry, file->f_path.mnt, &newattrs, file);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
mnt_drop_write(file->f_path.mnt);
|
||||
out_putf:
|
||||
@@ -651,7 +647,7 @@ asmlinkage long sys_chmod(const char __u
|
||||
}
|
||||
|
||||
static int chown_common(struct dentry * dentry, struct vfsmount *mnt,
|
||||
- uid_t user, gid_t group)
|
||||
+ uid_t user, gid_t group, struct file *file)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
int error;
|
||||
@@ -670,7 +666,7 @@ static int chown_common(struct dentry *
|
||||
newattrs.ia_valid |=
|
||||
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
|
||||
mutex_lock(&inode->i_mutex);
|
||||
- error = notify_change(dentry, mnt, &newattrs);
|
||||
+ error = fnotify_change(dentry, mnt, &newattrs, file);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
||||
return error;
|
||||
@@ -687,7 +683,7 @@ asmlinkage long sys_chown(const char __u
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (error)
|
||||
goto out_release;
|
||||
- error = chown_common(path.dentry, path.mnt, user, group);
|
||||
+ error = chown_common(path.dentry, path.mnt, user, group, NULL);
|
||||
mnt_drop_write(path.mnt);
|
||||
out_release:
|
||||
path_put(&path);
|
||||
@@ -712,7 +708,7 @@ asmlinkage long sys_fchownat(int dfd, co
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (error)
|
||||
goto out_release;
|
||||
- error = chown_common(path.dentry, path.mnt, user, group);
|
||||
+ error = chown_common(path.dentry, path.mnt, user, group, NULL);
|
||||
mnt_drop_write(path.mnt);
|
||||
out_release:
|
||||
path_put(&path);
|
||||
@@ -731,7 +727,7 @@ asmlinkage long sys_lchown(const char __
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (error)
|
||||
goto out_release;
|
||||
- error = chown_common(path.dentry, path.mnt, user, group);
|
||||
+ error = chown_common(path.dentry, path.mnt, user, group, NULL);
|
||||
mnt_drop_write(path.mnt);
|
||||
out_release:
|
||||
path_put(&path);
|
||||
@@ -755,7 +751,7 @@ asmlinkage long sys_fchown(unsigned int
|
||||
goto out_fput;
|
||||
dentry = file->f_path.dentry;
|
||||
audit_inode(NULL, dentry);
|
||||
- error = chown_common(dentry, file->f_path.mnt, user, group);
|
||||
+ error = chown_common(dentry, file->f_path.mnt, user, group, file);
|
||||
mnt_drop_write(file->f_path.mnt);
|
||||
out_fput:
|
||||
fput(file);
|
||||
--- a/fs/utimes.c
|
||||
+++ b/fs/utimes.c
|
||||
@@ -48,7 +48,8 @@ static bool nsec_valid(long nsec)
|
||||
return nsec >= 0 && nsec <= 999999999;
|
||||
}
|
||||
|
||||
-static int utimes_common(struct path *path, struct timespec *times)
|
||||
+static int utimes_common(struct path *path, struct timespec *times,
|
||||
+ struct file *f)
|
||||
{
|
||||
int error;
|
||||
struct iattr newattrs;
|
||||
@@ -102,7 +103,7 @@ static int utimes_common(struct path *pa
|
||||
}
|
||||
}
|
||||
mutex_lock(&inode->i_mutex);
|
||||
- error = notify_change(path->dentry, path->mnt, &newattrs);
|
||||
+ error = fnotify_change(path->dentry, path->mnt, &newattrs, f);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
||||
mnt_drop_write_and_out:
|
||||
@@ -149,7 +150,7 @@ long do_utimes(int dfd, char __user *fil
|
||||
if (!file)
|
||||
goto out;
|
||||
|
||||
- error = utimes_common(&file->f_path, times);
|
||||
+ error = utimes_common(&file->f_path, times, file);
|
||||
fput(file);
|
||||
} else {
|
||||
struct path path;
|
||||
@@ -162,7 +163,7 @@ long do_utimes(int dfd, char __user *fil
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
- error = utimes_common(&path, times);
|
||||
+ error = utimes_common(&path, times, NULL);
|
||||
path_put(&path);
|
||||
}
|
||||
|
||||
--- a/include/linux/fs.h
|
||||
+++ b/include/linux/fs.h
|
||||
@@ -367,13 +367,6 @@ struct iattr {
|
||||
struct timespec ia_atime;
|
||||
struct timespec ia_mtime;
|
||||
struct timespec ia_ctime;
|
||||
-
|
||||
- /*
|
||||
- * Not an attribute, but an auxilary info for filesystems wanting to
|
||||
- * implement an ftruncate() like method. NOTE: filesystem should
|
||||
- * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL).
|
||||
- */
|
||||
- struct file *ia_file;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1306,6 +1299,7 @@ struct file_operations {
|
||||
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
|
||||
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
|
||||
int (*setlease)(struct file *, long, struct file_lock **);
|
||||
+ int (*fsetattr)(struct file *, struct iattr *);
|
||||
};
|
||||
|
||||
struct inode_operations {
|
||||
@@ -1831,6 +1825,7 @@ extern int do_remount_sb(struct super_bl
|
||||
extern sector_t bmap(struct inode *, sector_t);
|
||||
#endif
|
||||
extern int notify_change(struct dentry *, struct vfsmount *, struct iattr *);
|
||||
+extern int fnotify_change(struct dentry *, struct vfsmount *, struct iattr *, struct file *);
|
||||
extern int inode_permission(struct inode *, int);
|
||||
extern int generic_permission(struct inode *, int,
|
||||
int (*check_acl)(struct inode *, int));
|
55
kernel-patches/2.6.28/mount-capability.diff
Normal file
55
kernel-patches/2.6.28/mount-capability.diff
Normal file
|
@ -0,0 +1,55 @@
|
|||
---
|
||||
security/apparmor/lsm.c | 28 ----------------------------
|
||||
1 file changed, 28 deletions(-)
|
||||
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -143,20 +143,6 @@ static int param_set_aa_enabled(const ch
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int aa_reject_syscall(struct task_struct *task, gfp_t flags,
|
||||
- const char *name)
|
||||
-{
|
||||
- struct aa_profile *profile = aa_get_profile(task);
|
||||
- int error = 0;
|
||||
-
|
||||
- if (profile) {
|
||||
- error = aa_audit_syscallreject(profile, flags, name);
|
||||
- aa_put_profile(profile);
|
||||
- }
|
||||
-
|
||||
- return error;
|
||||
-}
|
||||
-
|
||||
static int apparmor_ptrace(struct task_struct *tracer,
|
||||
struct task_struct *tracee)
|
||||
{
|
||||
@@ -292,17 +278,6 @@ static int apparmor_bprm_secureexec(stru
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int apparmor_sb_mount(char *dev_name, struct path *path, char *type,
|
||||
- unsigned long flags, void *data)
|
||||
-{
|
||||
- return aa_reject_syscall(current, GFP_KERNEL, "mount");
|
||||
-}
|
||||
-
|
||||
-static int apparmor_umount(struct vfsmount *mnt, int flags)
|
||||
-{
|
||||
- return aa_reject_syscall(current, GFP_KERNEL, "umount");
|
||||
-}
|
||||
-
|
||||
static int apparmor_inode_mkdir(struct inode *dir, struct dentry *dentry,
|
||||
struct vfsmount *mnt, int mask)
|
||||
{
|
||||
@@ -925,9 +900,6 @@ struct security_operations apparmor_ops
|
||||
.bprm_set_security = apparmor_bprm_set_security,
|
||||
.bprm_secureexec = apparmor_bprm_secureexec,
|
||||
|
||||
- .sb_mount = apparmor_sb_mount,
|
||||
- .sb_umount = apparmor_umount,
|
||||
-
|
||||
.inode_mkdir = apparmor_inode_mkdir,
|
||||
.inode_rmdir = apparmor_inode_rmdir,
|
||||
.inode_create = apparmor_inode_create,
|
41
kernel-patches/2.6.28/remove_suid.diff
Normal file
41
kernel-patches/2.6.28/remove_suid.diff
Normal file
|
@ -0,0 +1,41 @@
|
|||
From: Andreas Gruenbacher <agruen@suse.de>
|
||||
Subject: Pass struct path down to remove_suid and children
|
||||
|
||||
Required by a later patch that adds a struct vfsmount parameter to
|
||||
notify_change().
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
|
||||
mm/filemap.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/mm/filemap.c
|
||||
+++ b/mm/filemap.c
|
||||
@@ -1773,12 +1773,12 @@ int should_remove_suid(struct dentry *de
|
||||
}
|
||||
EXPORT_SYMBOL(should_remove_suid);
|
||||
|
||||
-static int __remove_suid(struct dentry *dentry, int kill)
|
||||
+static int __remove_suid(struct path *path, int kill)
|
||||
{
|
||||
struct iattr newattrs;
|
||||
|
||||
newattrs.ia_valid = ATTR_FORCE | kill;
|
||||
- return notify_change(dentry, &newattrs);
|
||||
+ return notify_change(path->dentry, &newattrs);
|
||||
}
|
||||
|
||||
int file_remove_suid(struct file *file)
|
||||
@@ -1793,7 +1793,7 @@ int file_remove_suid(struct file *file)
|
||||
if (killpriv)
|
||||
error = security_inode_killpriv(dentry);
|
||||
if (!error && killsuid)
|
||||
- error = __remove_suid(dentry, killsuid);
|
||||
+ error = __remove_suid(&file->f_path, killsuid);
|
||||
|
||||
return error;
|
||||
}
|
34
kernel-patches/2.6.28/securit_default.diff
Normal file
34
kernel-patches/2.6.28/securit_default.diff
Normal file
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
security/Kconfig | 9 +++++++++
|
||||
security/security.c | 2 +-
|
||||
2 files changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/security/Kconfig
|
||||
+++ b/security/Kconfig
|
||||
@@ -59,6 +59,15 @@ config SECURITYFS
|
||||
|
||||
If you are unsure how to answer this question, answer N.
|
||||
|
||||
+config SECURITY_DEFAULT
|
||||
+ string "Default security module"
|
||||
+ depends on SECURITY
|
||||
+ default ""
|
||||
+ help
|
||||
+ This determines the security module used if the security=
|
||||
+ boot parmater is not provided. If a security module is not
|
||||
+ specified the first module to register will be used.
|
||||
+
|
||||
config SECURITY_NETWORK
|
||||
bool "Socket and Networking Security Hooks"
|
||||
depends on SECURITY
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <linux/security.h>
|
||||
|
||||
/* Boot-time LSM user choice */
|
||||
-static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1];
|
||||
+static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = CONFIG_SECURITY_DEFAULT;
|
||||
|
||||
/* things that live in capability.c */
|
||||
extern struct security_operations default_security_ops;
|
107
kernel-patches/2.6.28/security-create.diff
Normal file
107
kernel-patches/2.6.28/security-create.diff
Normal file
|
@ -0,0 +1,107 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Pass struct vfsmount to the inode_create LSM hook
|
||||
|
||||
This is needed for computing pathnames in the AppArmor LSM.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/namei.c | 2 +-
|
||||
include/linux/security.h | 9 ++++++---
|
||||
security/capability.c | 2 +-
|
||||
security/security.c | 5 +++--
|
||||
security/selinux/hooks.c | 3 ++-
|
||||
5 files changed, 13 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -1481,7 +1481,7 @@ int vfs_create(struct inode *dir, struct
|
||||
return -EACCES; /* shouldn't it be ENOSYS? */
|
||||
mode &= S_IALLUGO;
|
||||
mode |= S_IFREG;
|
||||
- error = security_inode_create(dir, dentry, mode);
|
||||
+ error = security_inode_create(dir, dentry, nd ? nd->path.mnt : NULL, mode);
|
||||
if (error)
|
||||
return error;
|
||||
DQUOT_INIT(dir);
|
||||
--- a/include/linux/security.h
|
||||
+++ b/include/linux/security.h
|
||||
@@ -337,6 +337,7 @@ static inline void security_free_mnt_opt
|
||||
* Check permission to create a regular file.
|
||||
* @dir contains inode structure of the parent of the new file.
|
||||
* @dentry contains the dentry structure for the file to be created.
|
||||
+ * @mnt is the vfsmount corresponding to @dentry (may be NULL).
|
||||
* @mode contains the file mode of the file to be created.
|
||||
* Return 0 if permission is granted.
|
||||
* @inode_link:
|
||||
@@ -1354,8 +1355,8 @@ struct security_operations {
|
||||
void (*inode_free_security) (struct inode *inode);
|
||||
int (*inode_init_security) (struct inode *inode, struct inode *dir,
|
||||
char **name, void **value, size_t *len);
|
||||
- int (*inode_create) (struct inode *dir,
|
||||
- struct dentry *dentry, int mode);
|
||||
+ int (*inode_create) (struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, int mode);
|
||||
int (*inode_link) (struct dentry *old_dentry,
|
||||
struct inode *dir, struct dentry *new_dentry);
|
||||
int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
|
||||
@@ -1618,7 +1619,8 @@ int security_inode_alloc(struct inode *i
|
||||
void security_inode_free(struct inode *inode);
|
||||
int security_inode_init_security(struct inode *inode, struct inode *dir,
|
||||
char **name, void **value, size_t *len);
|
||||
-int security_inode_create(struct inode *dir, struct dentry *dentry, int mode);
|
||||
+int security_inode_create(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, int mode);
|
||||
int security_inode_link(struct dentry *old_dentry, struct inode *dir,
|
||||
struct dentry *new_dentry);
|
||||
int security_inode_unlink(struct inode *dir, struct dentry *dentry);
|
||||
@@ -1973,6 +1975,7 @@ static inline int security_inode_init_se
|
||||
|
||||
static inline int security_inode_create(struct inode *dir,
|
||||
struct dentry *dentry,
|
||||
+ struct vfsmount *mnt,
|
||||
int mode)
|
||||
{
|
||||
return 0;
|
||||
--- a/security/capability.c
|
||||
+++ b/security/capability.c
|
||||
@@ -155,7 +155,7 @@ static int cap_inode_init_security(struc
|
||||
}
|
||||
|
||||
static int cap_inode_create(struct inode *inode, struct dentry *dentry,
|
||||
- int mask)
|
||||
+ struct vfsmount *mnt, int mask)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -367,11 +367,12 @@ int security_inode_init_security(struct
|
||||
}
|
||||
EXPORT_SYMBOL(security_inode_init_security);
|
||||
|
||||
-int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
|
||||
+int security_inode_create(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, int mode)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(dir)))
|
||||
return 0;
|
||||
- return security_ops->inode_create(dir, dentry, mode);
|
||||
+ return security_ops->inode_create(dir, dentry, mnt, mode);
|
||||
}
|
||||
|
||||
int security_inode_link(struct dentry *old_dentry, struct inode *dir,
|
||||
--- a/security/selinux/hooks.c
|
||||
+++ b/security/selinux/hooks.c
|
||||
@@ -2564,7 +2564,8 @@ static int selinux_inode_init_security(s
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
|
||||
+static int selinux_inode_create(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, int mask)
|
||||
{
|
||||
return may_create(dir, dentry, SECCLASS_FILE);
|
||||
}
|
128
kernel-patches/2.6.28/security-getxattr.diff
Normal file
128
kernel-patches/2.6.28/security-getxattr.diff
Normal file
|
@ -0,0 +1,128 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Pass struct vfsmount to the inode_getxattr LSM hook
|
||||
|
||||
This is needed for computing pathnames in the AppArmor LSM.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/xattr.c | 2 +-
|
||||
include/linux/security.h | 11 +++++++----
|
||||
security/capability.c | 3 ++-
|
||||
security/security.c | 5 +++--
|
||||
security/selinux/hooks.c | 3 ++-
|
||||
security/smack/smack_lsm.c | 4 +++-
|
||||
6 files changed, 18 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/fs/xattr.c
|
||||
+++ b/fs/xattr.c
|
||||
@@ -141,7 +141,7 @@ vfs_getxattr(struct dentry *dentry, stru
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
- error = security_inode_getxattr(dentry, name);
|
||||
+ error = security_inode_getxattr(dentry, mnt, name);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
--- a/include/linux/security.h
|
||||
+++ b/include/linux/security.h
|
||||
@@ -446,7 +446,7 @@ static inline void security_free_mnt_opt
|
||||
* @value identified by @name for @dentry and @mnt.
|
||||
* @inode_getxattr:
|
||||
* Check permission before obtaining the extended attributes
|
||||
- * identified by @name for @dentry.
|
||||
+ * identified by @name for @dentry and @mnt.
|
||||
* Return 0 if permission is granted.
|
||||
* @inode_listxattr:
|
||||
* Check permission before obtaining the list of extended attribute
|
||||
@@ -1400,7 +1400,8 @@ struct security_operations {
|
||||
struct vfsmount *mnt,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags);
|
||||
- int (*inode_getxattr) (struct dentry *dentry, const char *name);
|
||||
+ int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name);
|
||||
int (*inode_listxattr) (struct dentry *dentry);
|
||||
int (*inode_removexattr) (struct dentry *dentry, const char *name);
|
||||
int (*inode_need_killpriv) (struct dentry *dentry);
|
||||
@@ -1672,7 +1673,8 @@ int security_inode_setxattr(struct dentr
|
||||
void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags);
|
||||
-int security_inode_getxattr(struct dentry *dentry, const char *name);
|
||||
+int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name);
|
||||
int security_inode_listxattr(struct dentry *dentry);
|
||||
int security_inode_removexattr(struct dentry *dentry, const char *name);
|
||||
int security_inode_need_killpriv(struct dentry *dentry);
|
||||
@@ -2118,7 +2120,8 @@ static inline void security_inode_post_s
|
||||
{ }
|
||||
|
||||
static inline int security_inode_getxattr(struct dentry *dentry,
|
||||
- const char *name)
|
||||
+ struct vfsmount *mnt,
|
||||
+ const char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/capability.c
|
||||
+++ b/security/capability.c
|
||||
@@ -241,7 +241,8 @@ static void cap_inode_post_setxattr(stru
|
||||
{
|
||||
}
|
||||
|
||||
-static int cap_inode_getxattr(struct dentry *dentry, const char *name)
|
||||
+static int cap_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -500,11 +500,12 @@ void security_inode_post_setxattr(struct
|
||||
flags);
|
||||
}
|
||||
|
||||
-int security_inode_getxattr(struct dentry *dentry, const char *name)
|
||||
+int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(dentry->d_inode)))
|
||||
return 0;
|
||||
- return security_ops->inode_getxattr(dentry, name);
|
||||
+ return security_ops->inode_getxattr(dentry, mnt, name);
|
||||
}
|
||||
|
||||
int security_inode_listxattr(struct dentry *dentry)
|
||||
--- a/security/selinux/hooks.c
|
||||
+++ b/security/selinux/hooks.c
|
||||
@@ -2794,7 +2794,8 @@ static void selinux_inode_post_setxattr(
|
||||
return;
|
||||
}
|
||||
|
||||
-static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
|
||||
+static int selinux_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name)
|
||||
{
|
||||
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
|
||||
}
|
||||
--- a/security/smack/smack_lsm.c
|
||||
+++ b/security/smack/smack_lsm.c
|
||||
@@ -671,11 +671,13 @@ static void smack_inode_post_setxattr(st
|
||||
/*
|
||||
* smack_inode_getxattr - Smack check on getxattr
|
||||
* @dentry: the object
|
||||
+ * @mnt: unused
|
||||
* @name: unused
|
||||
*
|
||||
* Returns 0 if access is permitted, an error code otherwise
|
||||
*/
|
||||
-static int smack_inode_getxattr(struct dentry *dentry, const char *name)
|
||||
+static int smack_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name)
|
||||
{
|
||||
return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ);
|
||||
}
|
149
kernel-patches/2.6.28/security-link.diff
Normal file
149
kernel-patches/2.6.28/security-link.diff
Normal file
|
@ -0,0 +1,149 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Pass the struct vfsmounts to the inode_link LSM hook
|
||||
|
||||
This is needed for computing pathnames in the AppArmor LSM.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/namei.c | 3 ++-
|
||||
include/linux/security.h | 18 ++++++++++++------
|
||||
security/capability.c | 5 +++--
|
||||
security/security.c | 8 +++++---
|
||||
security/selinux/hooks.c | 9 +++++++--
|
||||
security/smack/smack_lsm.c | 5 +++--
|
||||
6 files changed, 32 insertions(+), 16 deletions(-)
|
||||
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -2391,7 +2391,8 @@ int vfs_link(struct dentry *old_dentry,
|
||||
if (S_ISDIR(inode->i_mode))
|
||||
return -EPERM;
|
||||
|
||||
- error = security_inode_link(old_dentry, dir, new_dentry);
|
||||
+ error = security_inode_link(old_dentry, old_mnt, dir, new_dentry,
|
||||
+ new_mnt);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
--- a/include/linux/security.h
|
||||
+++ b/include/linux/security.h
|
||||
@@ -343,8 +343,10 @@ static inline void security_free_mnt_opt
|
||||
* @inode_link:
|
||||
* Check permission before creating a new hard link to a file.
|
||||
* @old_dentry contains the dentry structure for an existing link to the file.
|
||||
+ * @old_mnt is the vfsmount corresponding to @old_dentry (may be NULL).
|
||||
* @dir contains the inode structure of the parent directory of the new link.
|
||||
* @new_dentry contains the dentry structure for the new link.
|
||||
+ * @new_mnt is the vfsmount corresponding to @new_dentry (may be NULL).
|
||||
* Return 0 if permission is granted.
|
||||
* @inode_unlink:
|
||||
* Check the permission to remove a hard link to a file.
|
||||
@@ -1362,8 +1364,9 @@ struct security_operations {
|
||||
char **name, void **value, size_t *len);
|
||||
int (*inode_create) (struct inode *dir, struct dentry *dentry,
|
||||
struct vfsmount *mnt, int mode);
|
||||
- int (*inode_link) (struct dentry *old_dentry,
|
||||
- struct inode *dir, struct dentry *new_dentry);
|
||||
+ int (*inode_link) (struct dentry *old_dentry, struct vfsmount *old_mnt,
|
||||
+ struct inode *dir, struct dentry *new_dentry,
|
||||
+ struct vfsmount *new_mnt);
|
||||
int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
|
||||
int (*inode_symlink) (struct inode *dir, struct dentry *dentry,
|
||||
struct vfsmount *mnt, const char *old_name);
|
||||
@@ -1628,8 +1631,9 @@ int security_inode_init_security(struct
|
||||
char **name, void **value, size_t *len);
|
||||
int security_inode_create(struct inode *dir, struct dentry *dentry,
|
||||
struct vfsmount *mnt, int mode);
|
||||
-int security_inode_link(struct dentry *old_dentry, struct inode *dir,
|
||||
- struct dentry *new_dentry);
|
||||
+int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
|
||||
+ struct inode *dir, struct dentry *new_dentry,
|
||||
+ struct vfsmount *new_mnt);
|
||||
int security_inode_unlink(struct inode *dir, struct dentry *dentry);
|
||||
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
|
||||
struct vfsmount *mnt, const char *old_name);
|
||||
@@ -1992,8 +1996,10 @@ static inline int security_inode_create(
|
||||
}
|
||||
|
||||
static inline int security_inode_link(struct dentry *old_dentry,
|
||||
- struct inode *dir,
|
||||
- struct dentry *new_dentry)
|
||||
+ struct vfsmount *old_mnt,
|
||||
+ struct inode *dir,
|
||||
+ struct dentry *new_dentry,
|
||||
+ struct vfsmount *new_mnt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/capability.c
|
||||
+++ b/security/capability.c
|
||||
@@ -160,8 +160,9 @@ static int cap_inode_create(struct inode
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int cap_inode_link(struct dentry *old_dentry, struct inode *inode,
|
||||
- struct dentry *new_dentry)
|
||||
+static int cap_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
|
||||
+ struct inode *inode,
|
||||
+ struct dentry *new_dentry, struct vfsmount *new_mnt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -375,12 +375,14 @@ int security_inode_create(struct inode *
|
||||
return security_ops->inode_create(dir, dentry, mnt, mode);
|
||||
}
|
||||
|
||||
-int security_inode_link(struct dentry *old_dentry, struct inode *dir,
|
||||
- struct dentry *new_dentry)
|
||||
+int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
|
||||
+ struct inode *dir, struct dentry *new_dentry,
|
||||
+ struct vfsmount *new_mnt)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(old_dentry->d_inode)))
|
||||
return 0;
|
||||
- return security_ops->inode_link(old_dentry, dir, new_dentry);
|
||||
+ return security_ops->inode_link(old_dentry, old_mnt, dir,
|
||||
+ new_dentry, new_mnt);
|
||||
}
|
||||
|
||||
int security_inode_unlink(struct inode *dir, struct dentry *dentry)
|
||||
--- a/security/selinux/hooks.c
|
||||
+++ b/security/selinux/hooks.c
|
||||
@@ -2570,11 +2570,16 @@ static int selinux_inode_create(struct i
|
||||
return may_create(dir, dentry, SECCLASS_FILE);
|
||||
}
|
||||
|
||||
-static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
|
||||
+static int selinux_inode_link(struct dentry *old_dentry,
|
||||
+ struct vfsmount *old_mnt,
|
||||
+ struct inode *dir,
|
||||
+ struct dentry *new_dentry,
|
||||
+ struct vfsmount *new_mnt)
|
||||
{
|
||||
int rc;
|
||||
|
||||
- rc = secondary_ops->inode_link(old_dentry, dir, new_dentry);
|
||||
+ rc = secondary_ops->inode_link(old_dentry, old_mnt, dir, new_dentry,
|
||||
+ new_mnt);
|
||||
if (rc)
|
||||
return rc;
|
||||
return may_link(dir, old_dentry, MAY_LINK);
|
||||
--- a/security/smack/smack_lsm.c
|
||||
+++ b/security/smack/smack_lsm.c
|
||||
@@ -432,8 +432,9 @@ static int smack_inode_init_security(str
|
||||
*
|
||||
* Returns 0 if access is permitted, an error code otherwise
|
||||
*/
|
||||
-static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
|
||||
- struct dentry *new_dentry)
|
||||
+static int smack_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
|
||||
+ struct inode *dir,
|
||||
+ struct dentry *new_dentry, struct vfsmount *new_mnt)
|
||||
{
|
||||
int rc;
|
||||
char *isp;
|
105
kernel-patches/2.6.28/security-listxattr.diff
Normal file
105
kernel-patches/2.6.28/security-listxattr.diff
Normal file
|
@ -0,0 +1,105 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Pass struct vfsmount to the inode_listxattr LSM hook
|
||||
|
||||
This is needed for computing pathnames in the AppArmor LSM.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/xattr.c | 2 +-
|
||||
include/linux/security.h | 9 +++++----
|
||||
security/capability.c | 2 +-
|
||||
security/security.c | 4 ++--
|
||||
security/selinux/hooks.c | 2 +-
|
||||
5 files changed, 10 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/fs/xattr.c
|
||||
+++ b/fs/xattr.c
|
||||
@@ -174,7 +174,7 @@ vfs_listxattr(struct dentry *dentry, str
|
||||
struct inode *inode = dentry->d_inode;
|
||||
ssize_t error;
|
||||
|
||||
- error = security_inode_listxattr(dentry);
|
||||
+ error = security_inode_listxattr(dentry, mnt);
|
||||
if (error)
|
||||
return error;
|
||||
error = -EOPNOTSUPP;
|
||||
--- a/include/linux/security.h
|
||||
+++ b/include/linux/security.h
|
||||
@@ -450,7 +450,7 @@ static inline void security_free_mnt_opt
|
||||
* Return 0 if permission is granted.
|
||||
* @inode_listxattr:
|
||||
* Check permission before obtaining the list of extended attribute
|
||||
- * names for @dentry.
|
||||
+ * names for @dentry and @mnt.
|
||||
* Return 0 if permission is granted.
|
||||
* @inode_removexattr:
|
||||
* Check permission before removing the extended attribute
|
||||
@@ -1402,7 +1402,7 @@ struct security_operations {
|
||||
size_t size, int flags);
|
||||
int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
|
||||
const char *name);
|
||||
- int (*inode_listxattr) (struct dentry *dentry);
|
||||
+ int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt);
|
||||
int (*inode_removexattr) (struct dentry *dentry, const char *name);
|
||||
int (*inode_need_killpriv) (struct dentry *dentry);
|
||||
int (*inode_killpriv) (struct dentry *dentry);
|
||||
@@ -1675,7 +1675,7 @@ void security_inode_post_setxattr(struct
|
||||
size_t size, int flags);
|
||||
int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
const char *name);
|
||||
-int security_inode_listxattr(struct dentry *dentry);
|
||||
+int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt);
|
||||
int security_inode_removexattr(struct dentry *dentry, const char *name);
|
||||
int security_inode_need_killpriv(struct dentry *dentry);
|
||||
int security_inode_killpriv(struct dentry *dentry);
|
||||
@@ -2126,7 +2126,8 @@ static inline int security_inode_getxatt
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static inline int security_inode_listxattr(struct dentry *dentry)
|
||||
+static inline int security_inode_listxattr(struct dentry *dentry,
|
||||
+ struct vfsmount *mnt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/capability.c
|
||||
+++ b/security/capability.c
|
||||
@@ -247,7 +247,7 @@ static int cap_inode_getxattr(struct den
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int cap_inode_listxattr(struct dentry *dentry)
|
||||
+static int cap_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -508,11 +508,11 @@ int security_inode_getxattr(struct dentr
|
||||
return security_ops->inode_getxattr(dentry, mnt, name);
|
||||
}
|
||||
|
||||
-int security_inode_listxattr(struct dentry *dentry)
|
||||
+int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(dentry->d_inode)))
|
||||
return 0;
|
||||
- return security_ops->inode_listxattr(dentry);
|
||||
+ return security_ops->inode_listxattr(dentry, mnt);
|
||||
}
|
||||
|
||||
int security_inode_removexattr(struct dentry *dentry, const char *name)
|
||||
--- a/security/selinux/hooks.c
|
||||
+++ b/security/selinux/hooks.c
|
||||
@@ -2800,7 +2800,7 @@ static int selinux_inode_getxattr(struct
|
||||
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
|
||||
}
|
||||
|
||||
-static int selinux_inode_listxattr(struct dentry *dentry)
|
||||
+static int selinux_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt)
|
||||
{
|
||||
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
|
||||
}
|
106
kernel-patches/2.6.28/security-mkdir.diff
Normal file
106
kernel-patches/2.6.28/security-mkdir.diff
Normal file
|
@ -0,0 +1,106 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Pass struct vfsmount to the inode_mkdir LSM hook
|
||||
|
||||
This is needed for computing pathnames in the AppArmor LSM.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/namei.c | 2 +-
|
||||
include/linux/security.h | 8 ++++++--
|
||||
security/capability.c | 2 +-
|
||||
security/security.c | 5 +++--
|
||||
security/selinux/hooks.c | 3 ++-
|
||||
5 files changed, 13 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -2037,7 +2037,7 @@ int vfs_mkdir(struct inode *dir, struct
|
||||
return -EPERM;
|
||||
|
||||
mode &= (S_IRWXUGO|S_ISVTX);
|
||||
- error = security_inode_mkdir(dir, dentry, mode);
|
||||
+ error = security_inode_mkdir(dir, dentry, mnt, mode);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
--- a/include/linux/security.h
|
||||
+++ b/include/linux/security.h
|
||||
@@ -362,6 +362,7 @@ static inline void security_free_mnt_opt
|
||||
* associated with inode strcture @dir.
|
||||
* @dir containst the inode structure of parent of the directory to be created.
|
||||
* @dentry contains the dentry structure of new directory.
|
||||
+ * @mnt is the vfsmount corresponding to @dentry (may be NULL).
|
||||
* @mode contains the mode of new directory.
|
||||
* Return 0 if permission is granted.
|
||||
* @inode_rmdir:
|
||||
@@ -1363,7 +1364,8 @@ struct security_operations {
|
||||
int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
|
||||
int (*inode_symlink) (struct inode *dir,
|
||||
struct dentry *dentry, const char *old_name);
|
||||
- int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, int mode);
|
||||
+ int (*inode_mkdir) (struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, int mode);
|
||||
int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
|
||||
int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
|
||||
int mode, dev_t dev);
|
||||
@@ -1628,7 +1630,8 @@ int security_inode_link(struct dentry *o
|
||||
int security_inode_unlink(struct inode *dir, struct dentry *dentry);
|
||||
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
|
||||
const char *old_name);
|
||||
-int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode);
|
||||
+int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, int mode);
|
||||
int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
|
||||
int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
|
||||
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
@@ -2006,6 +2009,7 @@ static inline int security_inode_symlink
|
||||
|
||||
static inline int security_inode_mkdir(struct inode *dir,
|
||||
struct dentry *dentry,
|
||||
+ struct vfsmount *mnt,
|
||||
int mode)
|
||||
{
|
||||
return 0;
|
||||
--- a/security/capability.c
|
||||
+++ b/security/capability.c
|
||||
@@ -178,7 +178,7 @@ static int cap_inode_symlink(struct inod
|
||||
}
|
||||
|
||||
static int cap_inode_mkdir(struct inode *inode, struct dentry *dentry,
|
||||
- int mask)
|
||||
+ struct vfsmount *mnt, int mask)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -398,11 +398,12 @@ int security_inode_symlink(struct inode
|
||||
return security_ops->inode_symlink(dir, dentry, old_name);
|
||||
}
|
||||
|
||||
-int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
||||
+int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, int mode)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(dir)))
|
||||
return 0;
|
||||
- return security_ops->inode_mkdir(dir, dentry, mode);
|
||||
+ return security_ops->inode_mkdir(dir, dentry, mnt, mode);
|
||||
}
|
||||
|
||||
int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
--- a/security/selinux/hooks.c
|
||||
+++ b/security/selinux/hooks.c
|
||||
@@ -2595,7 +2595,8 @@ static int selinux_inode_symlink(struct
|
||||
return may_create(dir, dentry, SECCLASS_LNK_FILE);
|
||||
}
|
||||
|
||||
-static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
|
||||
+static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, int mask)
|
||||
{
|
||||
return may_create(dir, dentry, SECCLASS_DIR);
|
||||
}
|
124
kernel-patches/2.6.28/security-mknod.diff
Normal file
124
kernel-patches/2.6.28/security-mknod.diff
Normal file
|
@ -0,0 +1,124 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Pass struct vfsmount to the inode_mknod LSM hook
|
||||
|
||||
This is needed for computing pathnames in the AppArmor LSM.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/namei.c | 6 +++---
|
||||
include/linux/security.h | 7 +++++--
|
||||
security/capability.c | 2 +-
|
||||
security/security.c | 5 +++--
|
||||
security/selinux/hooks.c | 5 +++--
|
||||
5 files changed, 15 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -1942,7 +1942,7 @@ int vfs_mknod(struct inode *dir, struct
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
- error = security_inode_mknod(dir, dentry, mode, dev);
|
||||
+ error = security_inode_mknod(dir, dentry, mnt, mode, dev);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@@ -2004,11 +2004,11 @@ asmlinkage long sys_mknodat(int dfd, con
|
||||
break;
|
||||
case S_IFCHR: case S_IFBLK:
|
||||
error = vfs_mknod(nd.path.dentry->d_inode, dentry,
|
||||
- nd.path, mode, new_decode_dev(dev));
|
||||
+ nd.path.mnt, mode, new_decode_dev(dev));
|
||||
break;
|
||||
case S_IFIFO: case S_IFSOCK:
|
||||
error = vfs_mknod(nd.path.dentry->d_inode, dentry,
|
||||
- nd.path, mode, 0);
|
||||
+ nd.path.mnt, mode, 0);
|
||||
break;
|
||||
}
|
||||
mnt_drop_write(nd.path.mnt);
|
||||
--- a/include/linux/security.h
|
||||
+++ b/include/linux/security.h
|
||||
@@ -377,6 +377,7 @@ static inline void security_free_mnt_opt
|
||||
* and not this hook.
|
||||
* @dir contains the inode structure of parent of the new file.
|
||||
* @dentry contains the dentry structure of the new file.
|
||||
+ * @mnt is the vfsmount corresponding to @dentry (may be NULL).
|
||||
* @mode contains the mode of the new file.
|
||||
* @dev contains the device number.
|
||||
* Return 0 if permission is granted.
|
||||
@@ -1368,7 +1369,7 @@ struct security_operations {
|
||||
struct vfsmount *mnt, int mode);
|
||||
int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
|
||||
int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
|
||||
- int mode, dev_t dev);
|
||||
+ struct vfsmount *mnt, int mode, dev_t dev);
|
||||
int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
|
||||
struct inode *new_dir, struct dentry *new_dentry);
|
||||
int (*inode_readlink) (struct dentry *dentry);
|
||||
@@ -1633,7 +1634,8 @@ int security_inode_symlink(struct inode
|
||||
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
|
||||
struct vfsmount *mnt, int mode);
|
||||
int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
|
||||
-int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
|
||||
+int security_inode_mknod(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, int mode, dev_t dev);
|
||||
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
struct inode *new_dir, struct dentry *new_dentry);
|
||||
int security_inode_readlink(struct dentry *dentry);
|
||||
@@ -2023,6 +2025,7 @@ static inline int security_inode_rmdir(s
|
||||
|
||||
static inline int security_inode_mknod(struct inode *dir,
|
||||
struct dentry *dentry,
|
||||
+ struct vfsmount *mnt,
|
||||
int mode, dev_t dev)
|
||||
{
|
||||
return 0;
|
||||
--- a/security/capability.c
|
||||
+++ b/security/capability.c
|
||||
@@ -189,7 +189,7 @@ static int cap_inode_rmdir(struct inode
|
||||
}
|
||||
|
||||
static int cap_inode_mknod(struct inode *inode, struct dentry *dentry,
|
||||
- int mode, dev_t dev)
|
||||
+ struct vfsmount *mnt, int mode, dev_t dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -413,11 +413,12 @@ int security_inode_rmdir(struct inode *d
|
||||
return security_ops->inode_rmdir(dir, dentry);
|
||||
}
|
||||
|
||||
-int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
|
||||
+int security_inode_mknod(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, int mode, dev_t dev)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(dir)))
|
||||
return 0;
|
||||
- return security_ops->inode_mknod(dir, dentry, mode, dev);
|
||||
+ return security_ops->inode_mknod(dir, dentry, mnt, mode, dev);
|
||||
}
|
||||
|
||||
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
--- a/security/selinux/hooks.c
|
||||
+++ b/security/selinux/hooks.c
|
||||
@@ -2606,11 +2606,12 @@ static int selinux_inode_rmdir(struct in
|
||||
return may_link(dir, dentry, MAY_RMDIR);
|
||||
}
|
||||
|
||||
-static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
|
||||
+static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, int mode, dev_t dev)
|
||||
{
|
||||
int rc;
|
||||
|
||||
- rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
|
||||
+ rc = secondary_ops->inode_mknod(dir, dentry, mnt, mode, dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
104
kernel-patches/2.6.28/security-readlink.diff
Normal file
104
kernel-patches/2.6.28/security-readlink.diff
Normal file
|
@ -0,0 +1,104 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Pass struct vfsmount to the inode_readlink LSM hook
|
||||
|
||||
This is needed for computing pathnames in the AppArmor LSM.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/stat.c | 2 +-
|
||||
include/linux/security.h | 8 +++++---
|
||||
security/capability.c | 2 +-
|
||||
security/security.c | 4 ++--
|
||||
security/selinux/hooks.c | 2 +-
|
||||
5 files changed, 10 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/fs/stat.c
|
||||
+++ b/fs/stat.c
|
||||
@@ -306,7 +306,7 @@ asmlinkage long sys_readlinkat(int dfd,
|
||||
|
||||
error = -EINVAL;
|
||||
if (inode->i_op && inode->i_op->readlink) {
|
||||
- error = security_inode_readlink(path.dentry);
|
||||
+ error = security_inode_readlink(path.dentry, path.mnt);
|
||||
if (!error) {
|
||||
touch_atime(path.mnt, path.dentry);
|
||||
error = inode->i_op->readlink(path.dentry,
|
||||
--- a/include/linux/security.h
|
||||
+++ b/include/linux/security.h
|
||||
@@ -392,6 +392,7 @@ static inline void security_free_mnt_opt
|
||||
* @inode_readlink:
|
||||
* Check the permission to read the symbolic link.
|
||||
* @dentry contains the dentry structure for the file link.
|
||||
+ * @mnt is the vfsmount corresponding to @dentry (may be NULL).
|
||||
* Return 0 if permission is granted.
|
||||
* @inode_follow_link:
|
||||
* Check permission to follow a symbolic link when looking up a pathname.
|
||||
@@ -1373,7 +1374,7 @@ struct security_operations {
|
||||
struct vfsmount *mnt, int mode, dev_t dev);
|
||||
int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
|
||||
struct inode *new_dir, struct dentry *new_dentry);
|
||||
- int (*inode_readlink) (struct dentry *dentry);
|
||||
+ int (*inode_readlink) (struct dentry *dentry, struct vfsmount *mnt);
|
||||
int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
|
||||
int (*inode_permission) (struct inode *inode, int mask);
|
||||
int (*inode_setattr) (struct dentry *dentry, struct vfsmount *,
|
||||
@@ -1639,7 +1640,7 @@ int security_inode_mknod(struct inode *d
|
||||
struct vfsmount *mnt, int mode, dev_t dev);
|
||||
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
struct inode *new_dir, struct dentry *new_dentry);
|
||||
-int security_inode_readlink(struct dentry *dentry);
|
||||
+int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt);
|
||||
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
|
||||
int security_inode_permission(struct inode *inode, int mask);
|
||||
int security_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
@@ -2041,7 +2042,8 @@ static inline int security_inode_rename(
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static inline int security_inode_readlink(struct dentry *dentry)
|
||||
+static inline int security_inode_readlink(struct dentry *dentry,
|
||||
+ struct vfsmount *mnt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/capability.c
|
||||
+++ b/security/capability.c
|
||||
@@ -200,7 +200,7 @@ static int cap_inode_rename(struct inode
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int cap_inode_readlink(struct dentry *dentry)
|
||||
+static int cap_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -431,11 +431,11 @@ int security_inode_rename(struct inode *
|
||||
new_dir, new_dentry);
|
||||
}
|
||||
|
||||
-int security_inode_readlink(struct dentry *dentry)
|
||||
+int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(dentry->d_inode)))
|
||||
return 0;
|
||||
- return security_ops->inode_readlink(dentry);
|
||||
+ return security_ops->inode_readlink(dentry, mnt);
|
||||
}
|
||||
|
||||
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
|
||||
--- a/security/selinux/hooks.c
|
||||
+++ b/security/selinux/hooks.c
|
||||
@@ -2625,7 +2625,7 @@ static int selinux_inode_rename(struct i
|
||||
return may_rename(old_inode, old_dentry, new_inode, new_dentry);
|
||||
}
|
||||
|
||||
-static int selinux_inode_readlink(struct dentry *dentry)
|
||||
+static int selinux_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
|
||||
{
|
||||
return dentry_has_perm(current, NULL, dentry, FILE__READ);
|
||||
}
|
143
kernel-patches/2.6.28/security-removexattr.diff
Normal file
143
kernel-patches/2.6.28/security-removexattr.diff
Normal file
|
@ -0,0 +1,143 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Pass struct vfsmount to the inode_removexattr LSM hook
|
||||
|
||||
This is needed for computing pathnames in the AppArmor LSM.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/xattr.c | 2 +-
|
||||
include/linux/security.h | 14 +++++++++-----
|
||||
security/commoncap.c | 3 ++-
|
||||
security/security.c | 5 +++--
|
||||
security/selinux/hooks.c | 3 ++-
|
||||
security/smack/smack_lsm.c | 6 ++++--
|
||||
6 files changed, 21 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/fs/xattr.c
|
||||
+++ b/fs/xattr.c
|
||||
@@ -202,7 +202,7 @@ vfs_removexattr(struct dentry *dentry, s
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
- error = security_inode_removexattr(dentry, name);
|
||||
+ error = security_inode_removexattr(dentry, mnt, name);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
--- a/include/linux/security.h
|
||||
+++ b/include/linux/security.h
|
||||
@@ -57,7 +57,8 @@ extern int cap_bprm_secureexec(struct li
|
||||
extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
const char *name, const void *value, size_t size,
|
||||
int flags);
|
||||
-extern int cap_inode_removexattr(struct dentry *dentry, const char *name);
|
||||
+extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name);
|
||||
extern int cap_inode_need_killpriv(struct dentry *dentry);
|
||||
extern int cap_inode_killpriv(struct dentry *dentry);
|
||||
extern int cap_task_post_setuid(uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
|
||||
@@ -1403,7 +1404,8 @@ struct security_operations {
|
||||
int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
|
||||
const char *name);
|
||||
int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt);
|
||||
- int (*inode_removexattr) (struct dentry *dentry, const char *name);
|
||||
+ int (*inode_removexattr) (struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name);
|
||||
int (*inode_need_killpriv) (struct dentry *dentry);
|
||||
int (*inode_killpriv) (struct dentry *dentry);
|
||||
int (*inode_getsecurity) (const struct inode *inode, const char *name, void **buffer, bool alloc);
|
||||
@@ -1676,7 +1678,8 @@ void security_inode_post_setxattr(struct
|
||||
int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
const char *name);
|
||||
int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt);
|
||||
-int security_inode_removexattr(struct dentry *dentry, const char *name);
|
||||
+int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name);
|
||||
int security_inode_need_killpriv(struct dentry *dentry);
|
||||
int security_inode_killpriv(struct dentry *dentry);
|
||||
int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
|
||||
@@ -2133,9 +2136,10 @@ static inline int security_inode_listxat
|
||||
}
|
||||
|
||||
static inline int security_inode_removexattr(struct dentry *dentry,
|
||||
- const char *name)
|
||||
+ struct vfsmount *mnt,
|
||||
+ const char *name)
|
||||
{
|
||||
- return cap_inode_removexattr(dentry, name);
|
||||
+ return cap_inode_removexattr(dentry, mnt, name);
|
||||
}
|
||||
|
||||
static inline int security_inode_need_killpriv(struct dentry *dentry)
|
||||
--- a/security/commoncap.c
|
||||
+++ b/security/commoncap.c
|
||||
@@ -426,7 +426,8 @@ int cap_inode_setxattr(struct dentry *de
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int cap_inode_removexattr(struct dentry *dentry, const char *name)
|
||||
+int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name)
|
||||
{
|
||||
if (!strcmp(name, XATTR_NAME_CAPS)) {
|
||||
if (!capable(CAP_SETFCAP))
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -515,11 +515,12 @@ int security_inode_listxattr(struct dent
|
||||
return security_ops->inode_listxattr(dentry, mnt);
|
||||
}
|
||||
|
||||
-int security_inode_removexattr(struct dentry *dentry, const char *name)
|
||||
+int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(dentry->d_inode)))
|
||||
return 0;
|
||||
- return security_ops->inode_removexattr(dentry, name);
|
||||
+ return security_ops->inode_removexattr(dentry, mnt, name);
|
||||
}
|
||||
|
||||
int security_inode_need_killpriv(struct dentry *dentry)
|
||||
--- a/security/selinux/hooks.c
|
||||
+++ b/security/selinux/hooks.c
|
||||
@@ -2805,7 +2805,8 @@ static int selinux_inode_listxattr(struc
|
||||
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
|
||||
}
|
||||
|
||||
-static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
|
||||
+static int selinux_inode_removexattr(struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, const char *name)
|
||||
{
|
||||
if (strcmp(name, XATTR_NAME_SELINUX))
|
||||
return selinux_inode_setotherxattr(dentry, name);
|
||||
--- a/security/smack/smack_lsm.c
|
||||
+++ b/security/smack/smack_lsm.c
|
||||
@@ -685,13 +685,15 @@ static int smack_inode_getxattr(struct d
|
||||
/*
|
||||
* smack_inode_removexattr - Smack check on removexattr
|
||||
* @dentry: the object
|
||||
+ * @mnt: unused
|
||||
* @name: name of the attribute
|
||||
*
|
||||
* Removing the Smack attribute requires CAP_MAC_ADMIN
|
||||
*
|
||||
* Returns 0 if access is permitted, an error code otherwise
|
||||
*/
|
||||
-static int smack_inode_removexattr(struct dentry *dentry, const char *name)
|
||||
+static int smack_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
@@ -701,7 +703,7 @@ static int smack_inode_removexattr(struc
|
||||
if (!capable(CAP_MAC_ADMIN))
|
||||
rc = -EPERM;
|
||||
} else
|
||||
- rc = cap_inode_removexattr(dentry, name);
|
||||
+ rc = cap_inode_removexattr(dentry, mnt, name);
|
||||
|
||||
if (rc == 0)
|
||||
rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
|
160
kernel-patches/2.6.28/security-rename.diff
Normal file
160
kernel-patches/2.6.28/security-rename.diff
Normal file
|
@ -0,0 +1,160 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Pass struct vfsmount to the inode_rename LSM hook
|
||||
|
||||
This is needed for computing pathnames in the AppArmor LSM.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/namei.c | 6 ++++--
|
||||
include/linux/security.h | 13 ++++++++++---
|
||||
security/capability.c | 3 ++-
|
||||
security/security.c | 7 ++++---
|
||||
security/selinux/hooks.c | 8 ++++++--
|
||||
security/smack/smack_lsm.c | 6 +++++-
|
||||
6 files changed, 31 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -2518,7 +2518,8 @@ static int vfs_rename_dir(struct inode *
|
||||
return error;
|
||||
}
|
||||
|
||||
- error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry);
|
||||
+ error = security_inode_rename(old_dir, old_dentry, old_mnt,
|
||||
+ new_dir, new_dentry, new_mnt);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@@ -2552,7 +2553,8 @@ static int vfs_rename_other(struct inode
|
||||
struct inode *target;
|
||||
int error;
|
||||
|
||||
- error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry);
|
||||
+ error = security_inode_rename(old_dir, old_dentry, old_mnt,
|
||||
+ new_dir, new_dentry, new_mnt);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
--- a/include/linux/security.h
|
||||
+++ b/include/linux/security.h
|
||||
@@ -390,8 +390,10 @@ static inline void security_free_mnt_opt
|
||||
* Check for permission to rename a file or directory.
|
||||
* @old_dir contains the inode structure for parent of the old link.
|
||||
* @old_dentry contains the dentry structure of the old link.
|
||||
+ * @old_mnt is the vfsmount corresponding to @old_dentry (may be NULL).
|
||||
* @new_dir contains the inode structure for parent of the new link.
|
||||
* @new_dentry contains the dentry structure of the new link.
|
||||
+ * @new_mnt is the vfsmount corresponding to @new_dentry (may be NULL).
|
||||
* Return 0 if permission is granted.
|
||||
* @inode_readlink:
|
||||
* Check the permission to read the symbolic link.
|
||||
@@ -1380,7 +1382,9 @@ struct security_operations {
|
||||
int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
|
||||
struct vfsmount *mnt, int mode, dev_t dev);
|
||||
int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
|
||||
- struct inode *new_dir, struct dentry *new_dentry);
|
||||
+ struct vfsmount *old_mnt,
|
||||
+ struct inode *new_dir, struct dentry *new_dentry,
|
||||
+ struct vfsmount *new_mnt);
|
||||
int (*inode_readlink) (struct dentry *dentry, struct vfsmount *mnt);
|
||||
int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
|
||||
int (*inode_permission) (struct inode *inode, int mask);
|
||||
@@ -1649,7 +1653,8 @@ int security_inode_rmdir(struct inode *d
|
||||
int security_inode_mknod(struct inode *dir, struct dentry *dentry,
|
||||
struct vfsmount *mnt, int mode, dev_t dev);
|
||||
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
- struct inode *new_dir, struct dentry *new_dentry);
|
||||
+ struct vfsmount *old_mnt, struct inode *new_dir,
|
||||
+ struct dentry *new_dentry, struct vfsmount *new_mnt);
|
||||
int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt);
|
||||
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
|
||||
int security_inode_permission(struct inode *inode, int mask);
|
||||
@@ -2050,8 +2055,10 @@ static inline int security_inode_mknod(s
|
||||
|
||||
static inline int security_inode_rename(struct inode *old_dir,
|
||||
struct dentry *old_dentry,
|
||||
+ struct vfsmount *old_mnt,
|
||||
struct inode *new_dir,
|
||||
- struct dentry *new_dentry)
|
||||
+ struct dentry *new_dentry,
|
||||
+ struct vfsmount *new_mnt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/capability.c
|
||||
+++ b/security/capability.c
|
||||
@@ -198,7 +198,8 @@ static int cap_inode_mknod(struct inode
|
||||
}
|
||||
|
||||
static int cap_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
|
||||
- struct inode *new_inode, struct dentry *new_dentry)
|
||||
+ struct vfsmount *old_mnt, struct inode *new_inode,
|
||||
+ struct dentry *new_dentry, struct vfsmount *new_mnt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -426,13 +426,14 @@ int security_inode_mknod(struct inode *d
|
||||
}
|
||||
|
||||
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
- struct inode *new_dir, struct dentry *new_dentry)
|
||||
+ struct vfsmount *old_mnt, struct inode *new_dir,
|
||||
+ struct dentry *new_dentry, struct vfsmount *new_mnt)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
|
||||
(new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
|
||||
return 0;
|
||||
- return security_ops->inode_rename(old_dir, old_dentry,
|
||||
- new_dir, new_dentry);
|
||||
+ return security_ops->inode_rename(old_dir, old_dentry, old_mnt,
|
||||
+ new_dir, new_dentry, new_mnt);
|
||||
}
|
||||
|
||||
int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
|
||||
--- a/security/selinux/hooks.c
|
||||
+++ b/security/selinux/hooks.c
|
||||
@@ -2626,8 +2626,12 @@ static int selinux_inode_mknod(struct in
|
||||
return may_create(dir, dentry, inode_mode_to_security_class(mode));
|
||||
}
|
||||
|
||||
-static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
|
||||
- struct inode *new_inode, struct dentry *new_dentry)
|
||||
+static int selinux_inode_rename(struct inode *old_inode,
|
||||
+ struct dentry *old_dentry,
|
||||
+ struct vfsmount *old_mnt,
|
||||
+ struct inode *new_inode,
|
||||
+ struct dentry *new_dentry,
|
||||
+ struct vfsmount *new_mnt)
|
||||
{
|
||||
return may_rename(old_inode, old_dentry, new_inode, new_dentry);
|
||||
}
|
||||
--- a/security/smack/smack_lsm.c
|
||||
+++ b/security/smack/smack_lsm.c
|
||||
@@ -509,8 +509,10 @@ static int smack_inode_rmdir(struct inod
|
||||
* smack_inode_rename - Smack check on rename
|
||||
* @old_inode: the old directory
|
||||
* @old_dentry: unused
|
||||
+ * @old_mnt: unused
|
||||
* @new_inode: the new directory
|
||||
* @new_dentry: unused
|
||||
+ * @new_mnt: unused
|
||||
*
|
||||
* Read and write access is required on both the old and
|
||||
* new directories.
|
||||
@@ -519,8 +521,10 @@ static int smack_inode_rmdir(struct inod
|
||||
*/
|
||||
static int smack_inode_rename(struct inode *old_inode,
|
||||
struct dentry *old_dentry,
|
||||
+ struct vfsmount *old_mnt,
|
||||
struct inode *new_inode,
|
||||
- struct dentry *new_dentry)
|
||||
+ struct dentry *new_dentry,
|
||||
+ struct vfsmount *new_mnt)
|
||||
{
|
||||
int rc;
|
||||
char *isp;
|
127
kernel-patches/2.6.28/security-rmdir.diff
Normal file
127
kernel-patches/2.6.28/security-rmdir.diff
Normal file
|
@ -0,0 +1,127 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Pass struct vfsmount to the inode_rmdir LSM hook
|
||||
|
||||
This is needed for computing pathnames in the AppArmor LSM.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/namei.c | 2 +-
|
||||
include/linux/security.h | 10 +++++++---
|
||||
security/capability.c | 3 ++-
|
||||
security/security.c | 5 +++--
|
||||
security/selinux/hooks.c | 3 ++-
|
||||
security/smack/smack_lsm.c | 4 +++-
|
||||
6 files changed, 18 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -2132,7 +2132,7 @@ int vfs_rmdir(struct inode *dir, struct
|
||||
if (d_mountpoint(dentry))
|
||||
error = -EBUSY;
|
||||
else {
|
||||
- error = security_inode_rmdir(dir, dentry);
|
||||
+ error = security_inode_rmdir(dir, dentry, mnt);
|
||||
if (!error) {
|
||||
error = dir->i_op->rmdir(dir, dentry);
|
||||
if (!error)
|
||||
--- a/include/linux/security.h
|
||||
+++ b/include/linux/security.h
|
||||
@@ -372,6 +372,7 @@ static inline void security_free_mnt_opt
|
||||
* Check the permission to remove a directory.
|
||||
* @dir contains the inode structure of parent of the directory to be removed.
|
||||
* @dentry contains the dentry structure of directory to be removed.
|
||||
+ * @mnt is the vfsmount corresponding to @dentry (may be NULL).
|
||||
* Return 0 if permission is granted.
|
||||
* @inode_mknod:
|
||||
* Check permissions when creating a special file (or a socket or a fifo
|
||||
@@ -1372,7 +1373,8 @@ struct security_operations {
|
||||
struct vfsmount *mnt, const char *old_name);
|
||||
int (*inode_mkdir) (struct inode *dir, struct dentry *dentry,
|
||||
struct vfsmount *mnt, int mode);
|
||||
- int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
|
||||
+ int (*inode_rmdir) (struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt);
|
||||
int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
|
||||
struct vfsmount *mnt, int mode, dev_t dev);
|
||||
int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
|
||||
@@ -1639,7 +1641,8 @@ int security_inode_symlink(struct inode
|
||||
struct vfsmount *mnt, const char *old_name);
|
||||
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
|
||||
struct vfsmount *mnt, int mode);
|
||||
-int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
|
||||
+int security_inode_rmdir(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt);
|
||||
int security_inode_mknod(struct inode *dir, struct dentry *dentry,
|
||||
struct vfsmount *mnt, int mode, dev_t dev);
|
||||
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
@@ -2027,7 +2030,8 @@ static inline int security_inode_mkdir(s
|
||||
}
|
||||
|
||||
static inline int security_inode_rmdir(struct inode *dir,
|
||||
- struct dentry *dentry)
|
||||
+ struct dentry *dentry,
|
||||
+ struct vfsmount *mnt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/capability.c
|
||||
+++ b/security/capability.c
|
||||
@@ -184,7 +184,8 @@ static int cap_inode_mkdir(struct inode
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int cap_inode_rmdir(struct inode *inode, struct dentry *dentry)
|
||||
+static int cap_inode_rmdir(struct inode *inode, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -408,11 +408,12 @@ int security_inode_mkdir(struct inode *d
|
||||
return security_ops->inode_mkdir(dir, dentry, mnt, mode);
|
||||
}
|
||||
|
||||
-int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
+int security_inode_rmdir(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(dentry->d_inode)))
|
||||
return 0;
|
||||
- return security_ops->inode_rmdir(dir, dentry);
|
||||
+ return security_ops->inode_rmdir(dir, dentry, mnt);
|
||||
}
|
||||
|
||||
int security_inode_mknod(struct inode *dir, struct dentry *dentry,
|
||||
--- a/security/selinux/hooks.c
|
||||
+++ b/security/selinux/hooks.c
|
||||
@@ -2607,7 +2607,8 @@ static int selinux_inode_mkdir(struct in
|
||||
return may_create(dir, dentry, SECCLASS_DIR);
|
||||
}
|
||||
|
||||
-static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
+static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt)
|
||||
{
|
||||
return may_link(dir, dentry, MAY_RMDIR);
|
||||
}
|
||||
--- a/security/smack/smack_lsm.c
|
||||
+++ b/security/smack/smack_lsm.c
|
||||
@@ -480,11 +480,13 @@ static int smack_inode_unlink(struct ino
|
||||
* smack_inode_rmdir - Smack check on directory deletion
|
||||
* @dir: containing directory object
|
||||
* @dentry: directory to unlink
|
||||
+ * @mnt: vfsmount @dentry to unlink
|
||||
*
|
||||
* Returns 0 if current can write the containing directory
|
||||
* and the directory, error code otherwise
|
||||
*/
|
||||
-static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
+static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt)
|
||||
{
|
||||
int rc;
|
||||
|
139
kernel-patches/2.6.28/security-setattr.diff
Normal file
139
kernel-patches/2.6.28/security-setattr.diff
Normal file
|
@ -0,0 +1,139 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Pass struct vfsmount to the inode_setattr LSM hook
|
||||
|
||||
This is needed for computing pathnames in the AppArmor LSM.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/attr.c | 2 +-
|
||||
fs/fat/file.c | 2 +-
|
||||
include/linux/security.h | 10 +++++++---
|
||||
security/capability.c | 3 ++-
|
||||
security/security.c | 5 +++--
|
||||
security/selinux/hooks.c | 5 +++--
|
||||
security/smack/smack_lsm.c | 3 ++-
|
||||
7 files changed, 19 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/fs/attr.c
|
||||
+++ b/fs/attr.c
|
||||
@@ -160,7 +160,7 @@ int notify_change(struct dentry *dentry,
|
||||
if (!(attr->ia_valid & ~(ATTR_KILL_SUID | ATTR_KILL_SGID)))
|
||||
return 0;
|
||||
|
||||
- error = security_inode_setattr(dentry, attr);
|
||||
+ error = security_inode_setattr(dentry, mnt, attr);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
--- a/fs/fat/file.c
|
||||
+++ b/fs/fat/file.c
|
||||
@@ -93,7 +93,7 @@ int fat_generic_ioctl(struct inode *inod
|
||||
* out the RO attribute for checking by the security
|
||||
* module, just because it maps to a file mode.
|
||||
*/
|
||||
- err = security_inode_setattr(filp->f_path.dentry, &ia);
|
||||
+ err = security_inode_setattr(filp->f_path.dentry, filp->f_path.mnt, &ia);
|
||||
if (err)
|
||||
goto up;
|
||||
|
||||
--- a/include/linux/security.h
|
||||
+++ b/include/linux/security.h
|
||||
@@ -412,6 +412,7 @@ static inline void security_free_mnt_opt
|
||||
* file attributes change (such as when a file is truncated, chown/chmod
|
||||
* operations, transferring disk quotas, etc).
|
||||
* @dentry contains the dentry structure for the file.
|
||||
+ * @mnt is the vfsmount corresponding to @dentry (may be NULL).
|
||||
* @attr is the iattr structure containing the new file attributes.
|
||||
* Return 0 if permission is granted.
|
||||
* @inode_getattr:
|
||||
@@ -1371,7 +1372,8 @@ struct security_operations {
|
||||
int (*inode_readlink) (struct dentry *dentry);
|
||||
int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
|
||||
int (*inode_permission) (struct inode *inode, int mask);
|
||||
- int (*inode_setattr) (struct dentry *dentry, struct iattr *attr);
|
||||
+ int (*inode_setattr) (struct dentry *dentry, struct vfsmount *,
|
||||
+ struct iattr *attr);
|
||||
int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
|
||||
void (*inode_delete) (struct inode *inode);
|
||||
int (*inode_setxattr) (struct dentry *dentry, const char *name,
|
||||
@@ -1634,7 +1636,8 @@ int security_inode_rename(struct inode *
|
||||
int security_inode_readlink(struct dentry *dentry);
|
||||
int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
|
||||
int security_inode_permission(struct inode *inode, int mask);
|
||||
-int security_inode_setattr(struct dentry *dentry, struct iattr *attr);
|
||||
+int security_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ struct iattr *attr);
|
||||
int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
|
||||
void security_inode_delete(struct inode *inode);
|
||||
int security_inode_setxattr(struct dentry *dentry, const char *name,
|
||||
@@ -2046,7 +2049,8 @@ static inline int security_inode_permiss
|
||||
}
|
||||
|
||||
static inline int security_inode_setattr(struct dentry *dentry,
|
||||
- struct iattr *attr)
|
||||
+ struct vfsmount *mnt,
|
||||
+ struct iattr *attr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/capability.c
|
||||
+++ b/security/capability.c
|
||||
@@ -216,7 +216,8 @@ static int cap_inode_permission(struct i
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int cap_inode_setattr(struct dentry *dentry, struct iattr *iattr)
|
||||
+static int cap_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ struct iattr *iattr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -450,11 +450,12 @@ int security_inode_permission(struct ino
|
||||
return security_ops->inode_permission(inode, mask);
|
||||
}
|
||||
|
||||
-int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
+int security_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ struct iattr *attr)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(dentry->d_inode)))
|
||||
return 0;
|
||||
- return security_ops->inode_setattr(dentry, attr);
|
||||
+ return security_ops->inode_setattr(dentry, mnt, attr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(security_inode_setattr);
|
||||
|
||||
--- a/security/selinux/hooks.c
|
||||
+++ b/security/selinux/hooks.c
|
||||
@@ -2654,11 +2654,12 @@ static int selinux_inode_permission(stru
|
||||
open_file_mask_to_av(inode->i_mode, mask), NULL);
|
||||
}
|
||||
|
||||
-static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
|
||||
+static int selinux_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ struct iattr *iattr)
|
||||
{
|
||||
int rc;
|
||||
|
||||
- rc = secondary_ops->inode_setattr(dentry, iattr);
|
||||
+ rc = secondary_ops->inode_setattr(dentry, mnt, iattr);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
--- a/security/smack/smack_lsm.c
|
||||
+++ b/security/smack/smack_lsm.c
|
||||
@@ -559,7 +559,8 @@ static int smack_inode_permission(struct
|
||||
*
|
||||
* Returns 0 if access is permitted, an error code otherwise
|
||||
*/
|
||||
-static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
|
||||
+static int smack_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ struct iattr *iattr)
|
||||
{
|
||||
/*
|
||||
* Need to allow for clearing the setuid bit.
|
256
kernel-patches/2.6.28/security-setxattr.diff
Normal file
256
kernel-patches/2.6.28/security-setxattr.diff
Normal file
|
@ -0,0 +1,256 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Pass struct vfsmount to the inode_setxattr LSM hook
|
||||
|
||||
This is needed for computing pathnames in the AppArmor LSM.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/xattr.c | 4 ++--
|
||||
include/linux/security.h | 41 ++++++++++++++++++++++++++---------------
|
||||
security/capability.c | 3 ++-
|
||||
security/commoncap.c | 5 +++--
|
||||
security/security.c | 16 ++++++++++------
|
||||
security/selinux/hooks.c | 8 +++++---
|
||||
security/smack/smack_lsm.c | 12 ++++++++----
|
||||
7 files changed, 56 insertions(+), 33 deletions(-)
|
||||
|
||||
--- a/fs/xattr.c
|
||||
+++ b/fs/xattr.c
|
||||
@@ -78,7 +78,7 @@ vfs_setxattr(struct dentry *dentry, stru
|
||||
return error;
|
||||
|
||||
mutex_lock(&inode->i_mutex);
|
||||
- error = security_inode_setxattr(dentry, name, value, size, flags);
|
||||
+ error = security_inode_setxattr(dentry, mnt, name, value, size, flags);
|
||||
if (error)
|
||||
goto out;
|
||||
error = -EOPNOTSUPP;
|
||||
@@ -86,7 +86,7 @@ vfs_setxattr(struct dentry *dentry, stru
|
||||
error = inode->i_op->setxattr(dentry, name, value, size, flags);
|
||||
if (!error) {
|
||||
fsnotify_xattr(dentry);
|
||||
- security_inode_post_setxattr(dentry, name, value,
|
||||
+ security_inode_post_setxattr(dentry, mnt, name, value,
|
||||
size, flags);
|
||||
}
|
||||
} else if (!strncmp(name, XATTR_SECURITY_PREFIX,
|
||||
--- a/include/linux/security.h
|
||||
+++ b/include/linux/security.h
|
||||
@@ -54,8 +54,9 @@ extern void cap_capset_set(struct task_s
|
||||
extern int cap_bprm_set_security(struct linux_binprm *bprm);
|
||||
extern void cap_bprm_apply_creds(struct linux_binprm *bprm, int unsafe);
|
||||
extern int cap_bprm_secureexec(struct linux_binprm *bprm);
|
||||
-extern int cap_inode_setxattr(struct dentry *dentry, const char *name,
|
||||
- const void *value, size_t size, int flags);
|
||||
+extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name, const void *value, size_t size,
|
||||
+ int flags);
|
||||
extern int cap_inode_removexattr(struct dentry *dentry, const char *name);
|
||||
extern int cap_inode_need_killpriv(struct dentry *dentry);
|
||||
extern int cap_inode_killpriv(struct dentry *dentry);
|
||||
@@ -438,11 +439,11 @@ static inline void security_free_mnt_opt
|
||||
* inode.
|
||||
* @inode_setxattr:
|
||||
* Check permission before setting the extended attributes
|
||||
- * @value identified by @name for @dentry.
|
||||
+ * @value identified by @name for @dentry and @mnt.
|
||||
* Return 0 if permission is granted.
|
||||
* @inode_post_setxattr:
|
||||
* Update inode security field after successful setxattr operation.
|
||||
- * @value identified by @name for @dentry.
|
||||
+ * @value identified by @name for @dentry and @mnt.
|
||||
* @inode_getxattr:
|
||||
* Check permission before obtaining the extended attributes
|
||||
* identified by @name for @dentry.
|
||||
@@ -1392,10 +1393,13 @@ struct security_operations {
|
||||
struct iattr *attr);
|
||||
int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
|
||||
void (*inode_delete) (struct inode *inode);
|
||||
- int (*inode_setxattr) (struct dentry *dentry, const char *name,
|
||||
- const void *value, size_t size, int flags);
|
||||
- void (*inode_post_setxattr) (struct dentry *dentry, const char *name,
|
||||
- const void *value, size_t size, int flags);
|
||||
+ int (*inode_setxattr) (struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name, const void *value, size_t size,
|
||||
+ int flags);
|
||||
+ void (*inode_post_setxattr) (struct dentry *dentry,
|
||||
+ struct vfsmount *mnt,
|
||||
+ const char *name, const void *value,
|
||||
+ size_t size, int flags);
|
||||
int (*inode_getxattr) (struct dentry *dentry, const char *name);
|
||||
int (*inode_listxattr) (struct dentry *dentry);
|
||||
int (*inode_removexattr) (struct dentry *dentry, const char *name);
|
||||
@@ -1662,10 +1666,12 @@ int security_inode_setattr(struct dentry
|
||||
struct iattr *attr);
|
||||
int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
|
||||
void security_inode_delete(struct inode *inode);
|
||||
-int security_inode_setxattr(struct dentry *dentry, const char *name,
|
||||
- const void *value, size_t size, int flags);
|
||||
-void security_inode_post_setxattr(struct dentry *dentry, const char *name,
|
||||
- const void *value, size_t size, int flags);
|
||||
+int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name, const void *value,
|
||||
+ size_t size, int flags);
|
||||
+void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name, const void *value,
|
||||
+ size_t size, int flags);
|
||||
int security_inode_getxattr(struct dentry *dentry, const char *name);
|
||||
int security_inode_listxattr(struct dentry *dentry);
|
||||
int security_inode_removexattr(struct dentry *dentry, const char *name);
|
||||
@@ -2097,13 +2103,18 @@ static inline void security_inode_delete
|
||||
{ }
|
||||
|
||||
static inline int security_inode_setxattr(struct dentry *dentry,
|
||||
- const char *name, const void *value, size_t size, int flags)
|
||||
+ struct vfsmount *mnt,
|
||||
+ const char *name, const void *value,
|
||||
+ size_t size, int flags)
|
||||
{
|
||||
- return cap_inode_setxattr(dentry, name, value, size, flags);
|
||||
+ return cap_inode_setxattr(dentry, mnt, name, value, size, flags);
|
||||
}
|
||||
|
||||
static inline void security_inode_post_setxattr(struct dentry *dentry,
|
||||
- const char *name, const void *value, size_t size, int flags)
|
||||
+ struct vfsmount *mnt,
|
||||
+ const char *name,
|
||||
+ const void *value,
|
||||
+ size_t size, int flags)
|
||||
{ }
|
||||
|
||||
static inline int security_inode_getxattr(struct dentry *dentry,
|
||||
--- a/security/capability.c
|
||||
+++ b/security/capability.c
|
||||
@@ -235,7 +235,8 @@ static void cap_inode_delete(struct inod
|
||||
{
|
||||
}
|
||||
|
||||
-static void cap_inode_post_setxattr(struct dentry *dentry, const char *name,
|
||||
+static void cap_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
}
|
||||
--- a/security/commoncap.c
|
||||
+++ b/security/commoncap.c
|
||||
@@ -411,8 +411,9 @@ int cap_bprm_secureexec (struct linux_bi
|
||||
current->egid != current->gid);
|
||||
}
|
||||
|
||||
-int cap_inode_setxattr(struct dentry *dentry, const char *name,
|
||||
- const void *value, size_t size, int flags)
|
||||
+int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name, const void *value, size_t size,
|
||||
+ int flags)
|
||||
{
|
||||
if (!strcmp(name, XATTR_NAME_CAPS)) {
|
||||
if (!capable(CAP_SETFCAP))
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -480,20 +480,24 @@ void security_inode_delete(struct inode
|
||||
security_ops->inode_delete(inode);
|
||||
}
|
||||
|
||||
-int security_inode_setxattr(struct dentry *dentry, const char *name,
|
||||
- const void *value, size_t size, int flags)
|
||||
+int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name, const void *value, size_t size,
|
||||
+ int flags)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(dentry->d_inode)))
|
||||
return 0;
|
||||
- return security_ops->inode_setxattr(dentry, name, value, size, flags);
|
||||
+ return security_ops->inode_setxattr(dentry, mnt, name, value, size,
|
||||
+ flags);
|
||||
}
|
||||
|
||||
-void security_inode_post_setxattr(struct dentry *dentry, const char *name,
|
||||
- const void *value, size_t size, int flags)
|
||||
+void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name, const void *value,
|
||||
+ size_t size, int flags)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(dentry->d_inode)))
|
||||
return;
|
||||
- security_ops->inode_post_setxattr(dentry, name, value, size, flags);
|
||||
+ security_ops->inode_post_setxattr(dentry, mnt, name, value, size,
|
||||
+ flags);
|
||||
}
|
||||
|
||||
int security_inode_getxattr(struct dentry *dentry, const char *name)
|
||||
--- a/security/selinux/hooks.c
|
||||
+++ b/security/selinux/hooks.c
|
||||
@@ -2711,8 +2711,9 @@ static int selinux_inode_setotherxattr(s
|
||||
return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
|
||||
}
|
||||
|
||||
-static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
|
||||
- const void *value, size_t size, int flags)
|
||||
+static int selinux_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name, const void *value,
|
||||
+ size_t size, int flags)
|
||||
{
|
||||
struct task_security_struct *tsec = current->security;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
@@ -2766,7 +2767,8 @@ static int selinux_inode_setxattr(struct
|
||||
&ad);
|
||||
}
|
||||
|
||||
-static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
|
||||
+static void selinux_inode_post_setxattr(struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, const char *name,
|
||||
const void *value, size_t size,
|
||||
int flags)
|
||||
{
|
||||
--- a/security/smack/smack_lsm.c
|
||||
+++ b/security/smack/smack_lsm.c
|
||||
@@ -595,6 +595,7 @@ static int smack_inode_getattr(struct vf
|
||||
/**
|
||||
* smack_inode_setxattr - Smack check for setting xattrs
|
||||
* @dentry: the object
|
||||
+ * @mnt: unused
|
||||
* @name: name of the attribute
|
||||
* @value: unused
|
||||
* @size: unused
|
||||
@@ -604,8 +605,9 @@ static int smack_inode_getattr(struct vf
|
||||
*
|
||||
* Returns 0 if access is permitted, an error code otherwise
|
||||
*/
|
||||
-static int smack_inode_setxattr(struct dentry *dentry, const char *name,
|
||||
- const void *value, size_t size, int flags)
|
||||
+static int smack_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *name, const void *value,
|
||||
+ size_t size, int flags)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
@@ -615,7 +617,7 @@ static int smack_inode_setxattr(struct d
|
||||
if (!capable(CAP_MAC_ADMIN))
|
||||
rc = -EPERM;
|
||||
} else
|
||||
- rc = cap_inode_setxattr(dentry, name, value, size, flags);
|
||||
+ rc = cap_inode_setxattr(dentry, mnt, name, value, size, flags);
|
||||
|
||||
if (rc == 0)
|
||||
rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
|
||||
@@ -626,6 +628,7 @@ static int smack_inode_setxattr(struct d
|
||||
/**
|
||||
* smack_inode_post_setxattr - Apply the Smack update approved above
|
||||
* @dentry: object
|
||||
+ * @mnt: unused
|
||||
* @name: attribute name
|
||||
* @value: attribute value
|
||||
* @size: attribute size
|
||||
@@ -634,7 +637,8 @@ static int smack_inode_setxattr(struct d
|
||||
* Set the pointer in the inode blob to the entry found
|
||||
* in the master label list.
|
||||
*/
|
||||
-static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
|
||||
+static void smack_inode_post_setxattr(struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
struct inode_smack *isp;
|
105
kernel-patches/2.6.28/security-symlink.diff
Normal file
105
kernel-patches/2.6.28/security-symlink.diff
Normal file
|
@ -0,0 +1,105 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Pass struct vfsmount to the inode_symlink LSM hook
|
||||
|
||||
This is needed for computing pathnames in the AppArmor LSM.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/namei.c | 2 +-
|
||||
include/linux/security.h | 8 +++++---
|
||||
security/capability.c | 2 +-
|
||||
security/security.c | 4 ++--
|
||||
security/selinux/hooks.c | 3 ++-
|
||||
5 files changed, 11 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -2312,7 +2312,7 @@ int vfs_symlink(struct inode *dir, struc
|
||||
if (!dir->i_op || !dir->i_op->symlink)
|
||||
return -EPERM;
|
||||
|
||||
- error = security_inode_symlink(dir, dentry, oldname);
|
||||
+ error = security_inode_symlink(dir, dentry, mnt, oldname);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
--- a/include/linux/security.h
|
||||
+++ b/include/linux/security.h
|
||||
@@ -355,6 +355,7 @@ static inline void security_free_mnt_opt
|
||||
* Check the permission to create a symbolic link to a file.
|
||||
* @dir contains the inode structure of parent directory of the symbolic link.
|
||||
* @dentry contains the dentry structure of the symbolic link.
|
||||
+ * @mnt is the vfsmount corresponding to @dentry (may be NULL).
|
||||
* @old_name contains the pathname of file.
|
||||
* Return 0 if permission is granted.
|
||||
* @inode_mkdir:
|
||||
@@ -1363,8 +1364,8 @@ struct security_operations {
|
||||
int (*inode_link) (struct dentry *old_dentry,
|
||||
struct inode *dir, struct dentry *new_dentry);
|
||||
int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
|
||||
- int (*inode_symlink) (struct inode *dir,
|
||||
- struct dentry *dentry, const char *old_name);
|
||||
+ int (*inode_symlink) (struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, const char *old_name);
|
||||
int (*inode_mkdir) (struct inode *dir, struct dentry *dentry,
|
||||
struct vfsmount *mnt, int mode);
|
||||
int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
|
||||
@@ -1630,7 +1631,7 @@ int security_inode_link(struct dentry *o
|
||||
struct dentry *new_dentry);
|
||||
int security_inode_unlink(struct inode *dir, struct dentry *dentry);
|
||||
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
|
||||
- const char *old_name);
|
||||
+ struct vfsmount *mnt, const char *old_name);
|
||||
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
|
||||
struct vfsmount *mnt, int mode);
|
||||
int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
|
||||
@@ -2004,6 +2005,7 @@ static inline int security_inode_unlink(
|
||||
|
||||
static inline int security_inode_symlink(struct inode *dir,
|
||||
struct dentry *dentry,
|
||||
+ struct vfsmount *mnt,
|
||||
const char *old_name)
|
||||
{
|
||||
return 0;
|
||||
--- a/security/capability.c
|
||||
+++ b/security/capability.c
|
||||
@@ -172,7 +172,7 @@ static int cap_inode_unlink(struct inode
|
||||
}
|
||||
|
||||
static int cap_inode_symlink(struct inode *inode, struct dentry *dentry,
|
||||
- const char *name)
|
||||
+ struct vfsmount *mnt, const char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -391,11 +391,11 @@ int security_inode_unlink(struct inode *
|
||||
}
|
||||
|
||||
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
|
||||
- const char *old_name)
|
||||
+ struct vfsmount *mnt, const char *old_name)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(dir)))
|
||||
return 0;
|
||||
- return security_ops->inode_symlink(dir, dentry, old_name);
|
||||
+ return security_ops->inode_symlink(dir, dentry, mnt, old_name);
|
||||
}
|
||||
|
||||
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
|
||||
--- a/security/selinux/hooks.c
|
||||
+++ b/security/selinux/hooks.c
|
||||
@@ -2590,7 +2590,8 @@ static int selinux_inode_unlink(struct i
|
||||
return may_link(dir, dentry, MAY_UNLINK);
|
||||
}
|
||||
|
||||
-static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
|
||||
+static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, const char *name)
|
||||
{
|
||||
return may_create(dir, dentry, SECCLASS_LNK_FILE);
|
||||
}
|
132
kernel-patches/2.6.28/security-unlink.diff
Normal file
132
kernel-patches/2.6.28/security-unlink.diff
Normal file
|
@ -0,0 +1,132 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Pass struct vfsmount to the inode_unlink LSM hook
|
||||
|
||||
This is needed for computing pathnames in the AppArmor LSM.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/namei.c | 2 +-
|
||||
include/linux/security.h | 10 +++++++---
|
||||
security/capability.c | 3 ++-
|
||||
security/security.c | 5 +++--
|
||||
security/selinux/hooks.c | 5 +++--
|
||||
security/smack/smack_lsm.c | 4 +++-
|
||||
6 files changed, 19 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -2215,7 +2215,7 @@ int vfs_unlink(struct inode *dir, struct
|
||||
if (d_mountpoint(dentry))
|
||||
error = -EBUSY;
|
||||
else {
|
||||
- error = security_inode_unlink(dir, dentry);
|
||||
+ error = security_inode_unlink(dir, dentry, mnt);
|
||||
if (!error)
|
||||
error = dir->i_op->unlink(dir, dentry);
|
||||
}
|
||||
--- a/include/linux/security.h
|
||||
+++ b/include/linux/security.h
|
||||
@@ -352,6 +352,7 @@ static inline void security_free_mnt_opt
|
||||
* Check the permission to remove a hard link to a file.
|
||||
* @dir contains the inode structure of parent directory of the file.
|
||||
* @dentry contains the dentry structure for file to be unlinked.
|
||||
+ * @mnt is the vfsmount corresponding to @dentry (may be NULL).
|
||||
* Return 0 if permission is granted.
|
||||
* @inode_symlink:
|
||||
* Check the permission to create a symbolic link to a file.
|
||||
@@ -1368,7 +1369,8 @@ struct security_operations {
|
||||
int (*inode_link) (struct dentry *old_dentry, struct vfsmount *old_mnt,
|
||||
struct inode *dir, struct dentry *new_dentry,
|
||||
struct vfsmount *new_mnt);
|
||||
- int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
|
||||
+ int (*inode_unlink) (struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt);
|
||||
int (*inode_symlink) (struct inode *dir, struct dentry *dentry,
|
||||
struct vfsmount *mnt, const char *old_name);
|
||||
int (*inode_mkdir) (struct inode *dir, struct dentry *dentry,
|
||||
@@ -1636,7 +1638,8 @@ int security_inode_create(struct inode *
|
||||
int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
|
||||
struct inode *dir, struct dentry *new_dentry,
|
||||
struct vfsmount *new_mnt);
|
||||
-int security_inode_unlink(struct inode *dir, struct dentry *dentry);
|
||||
+int security_inode_unlink(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt);
|
||||
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
|
||||
struct vfsmount *mnt, const char *old_name);
|
||||
int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
|
||||
@@ -2008,7 +2011,8 @@ static inline int security_inode_link(st
|
||||
}
|
||||
|
||||
static inline int security_inode_unlink(struct inode *dir,
|
||||
- struct dentry *dentry)
|
||||
+ struct dentry *dentry,
|
||||
+ struct vfsmount *mnt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/capability.c
|
||||
+++ b/security/capability.c
|
||||
@@ -167,7 +167,8 @@ static int cap_inode_link(struct dentry
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int cap_inode_unlink(struct inode *inode, struct dentry *dentry)
|
||||
+static int cap_inode_unlink(struct inode *inode, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -385,11 +385,12 @@ int security_inode_link(struct dentry *o
|
||||
new_dentry, new_mnt);
|
||||
}
|
||||
|
||||
-int security_inode_unlink(struct inode *dir, struct dentry *dentry)
|
||||
+int security_inode_unlink(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(dentry->d_inode)))
|
||||
return 0;
|
||||
- return security_ops->inode_unlink(dir, dentry);
|
||||
+ return security_ops->inode_unlink(dir, dentry, mnt);
|
||||
}
|
||||
|
||||
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
|
||||
--- a/security/selinux/hooks.c
|
||||
+++ b/security/selinux/hooks.c
|
||||
@@ -2585,11 +2585,12 @@ static int selinux_inode_link(struct den
|
||||
return may_link(dir, old_dentry, MAY_LINK);
|
||||
}
|
||||
|
||||
-static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
|
||||
+static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt)
|
||||
{
|
||||
int rc;
|
||||
|
||||
- rc = secondary_ops->inode_unlink(dir, dentry);
|
||||
+ rc = secondary_ops->inode_unlink(dir, dentry, mnt);
|
||||
if (rc)
|
||||
return rc;
|
||||
return may_link(dir, dentry, MAY_UNLINK);
|
||||
--- a/security/smack/smack_lsm.c
|
||||
+++ b/security/smack/smack_lsm.c
|
||||
@@ -454,11 +454,13 @@ static int smack_inode_link(struct dentr
|
||||
* smack_inode_unlink - Smack check on inode deletion
|
||||
* @dir: containing directory object
|
||||
* @dentry: file to unlink
|
||||
+ * @mnt: vfsmount of file to unlink
|
||||
*
|
||||
* Returns 0 if current can write the containing directory
|
||||
* and the object, error code otherwise
|
||||
*/
|
||||
-static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
|
||||
+static int smack_inode_unlink(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt)
|
||||
{
|
||||
struct inode *ip = dentry->d_inode;
|
||||
int rc;
|
592
kernel-patches/2.6.28/security-xattr-file.diff
Normal file
592
kernel-patches/2.6.28/security-xattr-file.diff
Normal file
|
@ -0,0 +1,592 @@
|
|||
From: Andreas Gruenbacher <agruen@suse.de>
|
||||
Subject: Pass struct file down the inode_*xattr security LSM hooks
|
||||
|
||||
This allows LSMs to also distinguish between file descriptor and path
|
||||
access for the xattr operations. (The other relevant operations are
|
||||
covered by the setattr hook.)
|
||||
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/xattr.c | 59 +++++++++++++++++++++++----------------------
|
||||
include/linux/security.h | 38 ++++++++++++++++------------
|
||||
include/linux/xattr.h | 9 +++---
|
||||
security/capability.c | 5 ++-
|
||||
security/commoncap.c | 4 +--
|
||||
security/security.c | 17 ++++++------
|
||||
security/selinux/hooks.c | 10 ++++---
|
||||
security/smack/smack_lsm.c | 14 ++++++----
|
||||
8 files changed, 87 insertions(+), 69 deletions(-)
|
||||
|
||||
--- a/fs/xattr.c
|
||||
+++ b/fs/xattr.c
|
||||
@@ -68,7 +68,7 @@ xattr_permission(struct inode *inode, co
|
||||
|
||||
int
|
||||
vfs_setxattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
|
||||
- const void *value, size_t size, int flags)
|
||||
+ const void *value, size_t size, int flags, struct file *file)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
int error;
|
||||
@@ -78,7 +78,7 @@ vfs_setxattr(struct dentry *dentry, stru
|
||||
return error;
|
||||
|
||||
mutex_lock(&inode->i_mutex);
|
||||
- error = security_inode_setxattr(dentry, mnt, name, value, size, flags);
|
||||
+ error = security_inode_setxattr(dentry, mnt, name, value, size, flags, file);
|
||||
if (error)
|
||||
goto out;
|
||||
error = -EOPNOTSUPP;
|
||||
@@ -132,7 +132,7 @@ EXPORT_SYMBOL_GPL(xattr_getsecurity);
|
||||
|
||||
ssize_t
|
||||
vfs_getxattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
|
||||
- void *value, size_t size)
|
||||
+ void *value, size_t size, struct file *file)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
int error;
|
||||
@@ -141,7 +141,7 @@ vfs_getxattr(struct dentry *dentry, stru
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
- error = security_inode_getxattr(dentry, mnt, name);
|
||||
+ error = security_inode_getxattr(dentry, mnt, name, file);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@@ -169,12 +169,12 @@ EXPORT_SYMBOL_GPL(vfs_getxattr);
|
||||
|
||||
ssize_t
|
||||
vfs_listxattr(struct dentry *dentry, struct vfsmount *mnt, char *list,
|
||||
- size_t size)
|
||||
+ size_t size, struct file *file)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
ssize_t error;
|
||||
|
||||
- error = security_inode_listxattr(dentry, mnt);
|
||||
+ error = security_inode_listxattr(dentry, mnt, file);
|
||||
if (error)
|
||||
return error;
|
||||
error = -EOPNOTSUPP;
|
||||
@@ -190,7 +190,8 @@ vfs_listxattr(struct dentry *dentry, str
|
||||
EXPORT_SYMBOL_GPL(vfs_listxattr);
|
||||
|
||||
int
|
||||
-vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, const char *name)
|
||||
+vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
|
||||
+ struct file *file)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
int error;
|
||||
@@ -202,7 +203,7 @@ vfs_removexattr(struct dentry *dentry, s
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
- error = security_inode_removexattr(dentry, mnt, name);
|
||||
+ error = security_inode_removexattr(dentry, mnt, name, file);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@@ -222,7 +223,7 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
|
||||
*/
|
||||
static long
|
||||
setxattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name,
|
||||
- const void __user *value, size_t size, int flags)
|
||||
+ const void __user *value, size_t size, int flags, struct file *file)
|
||||
{
|
||||
int error;
|
||||
void *kvalue = NULL;
|
||||
@@ -249,7 +250,7 @@ setxattr(struct dentry *dentry, struct v
|
||||
}
|
||||
}
|
||||
|
||||
- error = vfs_setxattr(dentry, mnt, kname, kvalue, size, flags);
|
||||
+ error = vfs_setxattr(dentry, mnt, kname, kvalue, size, flags, file);
|
||||
kfree(kvalue);
|
||||
return error;
|
||||
}
|
||||
@@ -266,7 +267,7 @@ sys_setxattr(const char __user *pathname
|
||||
return error;
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (!error) {
|
||||
- error = setxattr(path.dentry, path.mnt, name, value, size, flags);
|
||||
+ error = setxattr(path.dentry, path.mnt, name, value, size, flags, NULL);
|
||||
mnt_drop_write(path.mnt);
|
||||
}
|
||||
path_put(&path);
|
||||
@@ -285,7 +286,7 @@ sys_lsetxattr(const char __user *pathnam
|
||||
return error;
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (!error) {
|
||||
- error = setxattr(path.dentry, path.mnt, name, value, size, flags);
|
||||
+ error = setxattr(path.dentry, path.mnt, name, value, size, flags, NULL);
|
||||
mnt_drop_write(path.mnt);
|
||||
}
|
||||
path_put(&path);
|
||||
@@ -307,7 +308,8 @@ sys_fsetxattr(int fd, const char __user
|
||||
audit_inode(NULL, dentry);
|
||||
error = mnt_want_write(f->f_path.mnt);
|
||||
if (!error) {
|
||||
- error = setxattr(dentry, f->f_vfsmnt, name, value, size, flags);
|
||||
+ error = setxattr(dentry, f->f_vfsmnt, name, value, size, flags,
|
||||
+ f);
|
||||
mnt_drop_write(f->f_path.mnt);
|
||||
}
|
||||
fput(f);
|
||||
@@ -319,7 +321,7 @@ sys_fsetxattr(int fd, const char __user
|
||||
*/
|
||||
static ssize_t
|
||||
getxattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name,
|
||||
- void __user *value, size_t size)
|
||||
+ void __user *value, size_t size, struct file *file)
|
||||
{
|
||||
ssize_t error;
|
||||
void *kvalue = NULL;
|
||||
@@ -339,7 +341,7 @@ getxattr(struct dentry *dentry, struct v
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
- error = vfs_getxattr(dentry, mnt, kname, kvalue, size);
|
||||
+ error = vfs_getxattr(dentry, mnt, kname, kvalue, size, file);
|
||||
if (error > 0) {
|
||||
if (size && copy_to_user(value, kvalue, error))
|
||||
error = -EFAULT;
|
||||
@@ -362,7 +364,7 @@ sys_getxattr(const char __user *pathname
|
||||
error = user_path(pathname, &path);
|
||||
if (error)
|
||||
return error;
|
||||
- error = getxattr(path.dentry, path.mnt, name, value, size);
|
||||
+ error = getxattr(path.dentry, path.mnt, name, value, size, NULL);
|
||||
path_put(&path);
|
||||
return error;
|
||||
}
|
||||
@@ -377,7 +379,7 @@ sys_lgetxattr(const char __user *pathnam
|
||||
error = user_lpath(pathname, &path);
|
||||
if (error)
|
||||
return error;
|
||||
- error = getxattr(path.dentry, path.mnt, name, value, size);
|
||||
+ error = getxattr(path.dentry, path.mnt, name, value, size, NULL);
|
||||
path_put(&path);
|
||||
return error;
|
||||
}
|
||||
@@ -392,7 +394,7 @@ sys_fgetxattr(int fd, const char __user
|
||||
if (!f)
|
||||
return error;
|
||||
audit_inode(NULL, f->f_path.dentry);
|
||||
- error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size);
|
||||
+ error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size, f);
|
||||
fput(f);
|
||||
return error;
|
||||
}
|
||||
@@ -402,7 +404,7 @@ sys_fgetxattr(int fd, const char __user
|
||||
*/
|
||||
static ssize_t
|
||||
listxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *list,
|
||||
- size_t size)
|
||||
+ size_t size, struct file *file)
|
||||
{
|
||||
ssize_t error;
|
||||
char *klist = NULL;
|
||||
@@ -415,7 +417,7 @@ listxattr(struct dentry *dentry, struct
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
- error = vfs_listxattr(dentry, mnt, klist, size);
|
||||
+ error = vfs_listxattr(dentry, mnt, klist, size, file);
|
||||
if (error > 0) {
|
||||
if (size && copy_to_user(list, klist, error))
|
||||
error = -EFAULT;
|
||||
@@ -437,7 +439,7 @@ sys_listxattr(const char __user *pathnam
|
||||
error = user_path(pathname, &path);
|
||||
if (error)
|
||||
return error;
|
||||
- error = listxattr(path.dentry, path.mnt, list, size);
|
||||
+ error = listxattr(path.dentry, path.mnt, list, size, NULL);
|
||||
path_put(&path);
|
||||
return error;
|
||||
}
|
||||
@@ -451,7 +453,7 @@ sys_llistxattr(const char __user *pathna
|
||||
error = user_lpath(pathname, &path);
|
||||
if (error)
|
||||
return error;
|
||||
- error = listxattr(path.dentry, path.mnt, list, size);
|
||||
+ error = listxattr(path.dentry, path.mnt, list, size, NULL);
|
||||
path_put(&path);
|
||||
return error;
|
||||
}
|
||||
@@ -466,7 +468,7 @@ sys_flistxattr(int fd, char __user *list
|
||||
if (!f)
|
||||
return error;
|
||||
audit_inode(NULL, f->f_path.dentry);
|
||||
- error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size);
|
||||
+ error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size, f);
|
||||
fput(f);
|
||||
return error;
|
||||
}
|
||||
@@ -475,7 +477,8 @@ sys_flistxattr(int fd, char __user *list
|
||||
* Extended attribute REMOVE operations
|
||||
*/
|
||||
static long
|
||||
-removexattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name)
|
||||
+removexattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char __user *name, struct file *file)
|
||||
{
|
||||
int error;
|
||||
char kname[XATTR_NAME_MAX + 1];
|
||||
@@ -486,7 +489,7 @@ removexattr(struct dentry *dentry, struc
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
- return vfs_removexattr(dentry, mnt, kname);
|
||||
+ return vfs_removexattr(dentry, mnt, kname, file);
|
||||
}
|
||||
|
||||
asmlinkage long
|
||||
@@ -500,7 +503,7 @@ sys_removexattr(const char __user *pathn
|
||||
return error;
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (!error) {
|
||||
- error = removexattr(path.dentry, path.mnt, name);
|
||||
+ error = removexattr(path.dentry, path.mnt, name, NULL);
|
||||
mnt_drop_write(path.mnt);
|
||||
}
|
||||
path_put(&path);
|
||||
@@ -518,7 +521,7 @@ sys_lremovexattr(const char __user *path
|
||||
return error;
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (!error) {
|
||||
- error = removexattr(path.dentry, path.mnt, name);
|
||||
+ error = removexattr(path.dentry, path.mnt, name, NULL);
|
||||
mnt_drop_write(path.mnt);
|
||||
}
|
||||
path_put(&path);
|
||||
@@ -539,7 +542,7 @@ sys_fremovexattr(int fd, const char __us
|
||||
audit_inode(NULL, dentry);
|
||||
error = mnt_want_write(f->f_path.mnt);
|
||||
if (!error) {
|
||||
- error = removexattr(dentry, f->f_path.mnt, name);
|
||||
+ error = removexattr(dentry, f->f_path.mnt, name, f);
|
||||
mnt_drop_write(f->f_path.mnt);
|
||||
}
|
||||
fput(f);
|
||||
--- a/include/linux/security.h
|
||||
+++ b/include/linux/security.h
|
||||
@@ -56,9 +56,9 @@ extern void cap_bprm_apply_creds(struct
|
||||
extern int cap_bprm_secureexec(struct linux_binprm *bprm);
|
||||
extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
const char *name, const void *value, size_t size,
|
||||
- int flags);
|
||||
+ int flags, struct file *file);
|
||||
extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
- const char *name);
|
||||
+ const char *name, struct file *file);
|
||||
extern int cap_inode_need_killpriv(struct dentry *dentry);
|
||||
extern int cap_inode_killpriv(struct dentry *dentry);
|
||||
extern int cap_task_post_setuid(uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
|
||||
@@ -1396,16 +1396,17 @@ struct security_operations {
|
||||
void (*inode_delete) (struct inode *inode);
|
||||
int (*inode_setxattr) (struct dentry *dentry, struct vfsmount *mnt,
|
||||
const char *name, const void *value, size_t size,
|
||||
- int flags);
|
||||
+ int flags, struct file *file);
|
||||
void (*inode_post_setxattr) (struct dentry *dentry,
|
||||
struct vfsmount *mnt,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags);
|
||||
int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
|
||||
- const char *name);
|
||||
- int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt);
|
||||
+ const char *name, struct file *file);
|
||||
+ int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ struct file *file);
|
||||
int (*inode_removexattr) (struct dentry *dentry, struct vfsmount *mnt,
|
||||
- const char *name);
|
||||
+ const char *name, struct file *file);
|
||||
int (*inode_need_killpriv) (struct dentry *dentry);
|
||||
int (*inode_killpriv) (struct dentry *dentry);
|
||||
int (*inode_getsecurity) (const struct inode *inode, const char *name, void **buffer, bool alloc);
|
||||
@@ -1671,15 +1672,16 @@ int security_inode_getattr(struct vfsmou
|
||||
void security_inode_delete(struct inode *inode);
|
||||
int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
const char *name, const void *value,
|
||||
- size_t size, int flags);
|
||||
+ size_t size, int flags, struct file *file);
|
||||
void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags);
|
||||
int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
- const char *name);
|
||||
-int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt);
|
||||
+ const char *name, struct file *file);
|
||||
+int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ struct file *file);
|
||||
int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
- const char *name);
|
||||
+ const char *name, struct file *file);
|
||||
int security_inode_need_killpriv(struct dentry *dentry);
|
||||
int security_inode_killpriv(struct dentry *dentry);
|
||||
int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
|
||||
@@ -2110,9 +2112,10 @@ static inline void security_inode_delete
|
||||
static inline int security_inode_setxattr(struct dentry *dentry,
|
||||
struct vfsmount *mnt,
|
||||
const char *name, const void *value,
|
||||
- size_t size, int flags)
|
||||
+ size_t size, int flags,
|
||||
+ struct file *file)
|
||||
{
|
||||
- return cap_inode_setxattr(dentry, mnt, name, value, size, flags);
|
||||
+ return cap_inode_setxattr(dentry, mnt, name, value, size, flags, file);
|
||||
}
|
||||
|
||||
static inline void security_inode_post_setxattr(struct dentry *dentry,
|
||||
@@ -2124,22 +2127,25 @@ static inline void security_inode_post_s
|
||||
|
||||
static inline int security_inode_getxattr(struct dentry *dentry,
|
||||
struct vfsmount *mnt,
|
||||
- const char *name)
|
||||
+ const char *name,
|
||||
+ struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_inode_listxattr(struct dentry *dentry,
|
||||
- struct vfsmount *mnt)
|
||||
+ struct vfsmount *mnt,
|
||||
+ struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_inode_removexattr(struct dentry *dentry,
|
||||
struct vfsmount *mnt,
|
||||
- const char *name)
|
||||
+ const char *name,
|
||||
+ struct file *file)
|
||||
{
|
||||
- return cap_inode_removexattr(dentry, mnt, name);
|
||||
+ return cap_inode_removexattr(dentry, mnt, name, file);
|
||||
}
|
||||
|
||||
static inline int security_inode_need_killpriv(struct dentry *dentry)
|
||||
--- a/include/linux/xattr.h
|
||||
+++ b/include/linux/xattr.h
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/mount.h>
|
||||
+#include <linux/fs.h>
|
||||
|
||||
/* Namespaces */
|
||||
#define XATTR_OS2_PREFIX "os2."
|
||||
@@ -48,10 +49,10 @@ struct xattr_handler {
|
||||
};
|
||||
|
||||
ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
|
||||
-ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, const char *, void *, size_t);
|
||||
-ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list, size_t size);
|
||||
-int vfs_setxattr(struct dentry *, struct vfsmount *, const char *, const void *, size_t, int);
|
||||
-int vfs_removexattr(struct dentry *, struct vfsmount *mnt, const char *);
|
||||
+ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, const char *, void *, size_t, struct file *file);
|
||||
+ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list, size_t size, struct file *file);
|
||||
+int vfs_setxattr(struct dentry *, struct vfsmount *, const char *, const void *, size_t, int, struct file *file);
|
||||
+int vfs_removexattr(struct dentry *, struct vfsmount *mnt, const char *, struct file *file);
|
||||
|
||||
ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
|
||||
ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
|
||||
--- a/security/capability.c
|
||||
+++ b/security/capability.c
|
||||
@@ -242,12 +242,13 @@ static void cap_inode_post_setxattr(stru
|
||||
}
|
||||
|
||||
static int cap_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
- const char *name)
|
||||
+ const char *name, struct file *f)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int cap_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt)
|
||||
+static int cap_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ struct file *f)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
--- a/security/commoncap.c
|
||||
+++ b/security/commoncap.c
|
||||
@@ -413,7 +413,7 @@ int cap_bprm_secureexec (struct linux_bi
|
||||
|
||||
int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
const char *name, const void *value, size_t size,
|
||||
- int flags)
|
||||
+ int flags, struct file *file)
|
||||
{
|
||||
if (!strcmp(name, XATTR_NAME_CAPS)) {
|
||||
if (!capable(CAP_SETFCAP))
|
||||
@@ -427,7 +427,7 @@ int cap_inode_setxattr(struct dentry *de
|
||||
}
|
||||
|
||||
int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
- const char *name)
|
||||
+ const char *name, struct file *file)
|
||||
{
|
||||
if (!strcmp(name, XATTR_NAME_CAPS)) {
|
||||
if (!capable(CAP_SETFCAP))
|
||||
--- a/security/security.c
|
||||
+++ b/security/security.c
|
||||
@@ -482,12 +482,12 @@ void security_inode_delete(struct inode
|
||||
|
||||
int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
const char *name, const void *value, size_t size,
|
||||
- int flags)
|
||||
+ int flags, struct file *file)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(dentry->d_inode)))
|
||||
return 0;
|
||||
return security_ops->inode_setxattr(dentry, mnt, name, value, size,
|
||||
- flags);
|
||||
+ flags, file);
|
||||
}
|
||||
|
||||
void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
@@ -501,26 +501,27 @@ void security_inode_post_setxattr(struct
|
||||
}
|
||||
|
||||
int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
- const char *name)
|
||||
+ const char *name, struct file *file)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(dentry->d_inode)))
|
||||
return 0;
|
||||
- return security_ops->inode_getxattr(dentry, mnt, name);
|
||||
+ return security_ops->inode_getxattr(dentry, mnt, name, file);
|
||||
}
|
||||
|
||||
-int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt)
|
||||
+int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ struct file *file)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(dentry->d_inode)))
|
||||
return 0;
|
||||
- return security_ops->inode_listxattr(dentry, mnt);
|
||||
+ return security_ops->inode_listxattr(dentry, mnt, file);
|
||||
}
|
||||
|
||||
int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
- const char *name)
|
||||
+ const char *name, struct file *file)
|
||||
{
|
||||
if (unlikely(IS_PRIVATE(dentry->d_inode)))
|
||||
return 0;
|
||||
- return security_ops->inode_removexattr(dentry, mnt, name);
|
||||
+ return security_ops->inode_removexattr(dentry, mnt, name, file);
|
||||
}
|
||||
|
||||
int security_inode_need_killpriv(struct dentry *dentry)
|
||||
--- a/security/selinux/hooks.c
|
||||
+++ b/security/selinux/hooks.c
|
||||
@@ -2713,7 +2713,7 @@ static int selinux_inode_setotherxattr(s
|
||||
|
||||
static int selinux_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
const char *name, const void *value,
|
||||
- size_t size, int flags)
|
||||
+ size_t size, int flags, struct file *file)
|
||||
{
|
||||
struct task_security_struct *tsec = current->security;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
@@ -2795,18 +2795,20 @@ static void selinux_inode_post_setxattr(
|
||||
}
|
||||
|
||||
static int selinux_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
- const char *name)
|
||||
+ const char *name, struct file *file)
|
||||
{
|
||||
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
|
||||
}
|
||||
|
||||
-static int selinux_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt)
|
||||
+static int selinux_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ struct file *file)
|
||||
{
|
||||
return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
|
||||
}
|
||||
|
||||
static int selinux_inode_removexattr(struct dentry *dentry,
|
||||
- struct vfsmount *mnt, const char *name)
|
||||
+ struct vfsmount *mnt, const char *name,
|
||||
+ struct file *file)
|
||||
{
|
||||
if (strcmp(name, XATTR_NAME_SELINUX))
|
||||
return selinux_inode_setotherxattr(dentry, name);
|
||||
--- a/security/smack/smack_lsm.c
|
||||
+++ b/security/smack/smack_lsm.c
|
||||
@@ -600,6 +600,7 @@ static int smack_inode_getattr(struct vf
|
||||
* @value: unused
|
||||
* @size: unused
|
||||
* @flags: unused
|
||||
+ * @file: unused
|
||||
*
|
||||
* This protects the Smack attribute explicitly.
|
||||
*
|
||||
@@ -607,7 +608,7 @@ static int smack_inode_getattr(struct vf
|
||||
*/
|
||||
static int smack_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
const char *name, const void *value,
|
||||
- size_t size, int flags)
|
||||
+ size_t size, int flags, struct file *file)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
@@ -617,7 +618,8 @@ static int smack_inode_setxattr(struct d
|
||||
if (!capable(CAP_MAC_ADMIN))
|
||||
rc = -EPERM;
|
||||
} else
|
||||
- rc = cap_inode_setxattr(dentry, mnt, name, value, size, flags);
|
||||
+ rc = cap_inode_setxattr(dentry, mnt, name, value, size, flags,
|
||||
+ file);
|
||||
|
||||
if (rc == 0)
|
||||
rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
|
||||
@@ -673,11 +675,12 @@ static void smack_inode_post_setxattr(st
|
||||
* @dentry: the object
|
||||
* @mnt: unused
|
||||
* @name: unused
|
||||
+ * @file: unused
|
||||
*
|
||||
* Returns 0 if access is permitted, an error code otherwise
|
||||
*/
|
||||
static int smack_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
- const char *name)
|
||||
+ const char *name, struct file *file)
|
||||
{
|
||||
return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ);
|
||||
}
|
||||
@@ -687,13 +690,14 @@ static int smack_inode_getxattr(struct d
|
||||
* @dentry: the object
|
||||
* @mnt: unused
|
||||
* @name: name of the attribute
|
||||
+ * @file: unused
|
||||
*
|
||||
* Removing the Smack attribute requires CAP_MAC_ADMIN
|
||||
*
|
||||
* Returns 0 if access is permitted, an error code otherwise
|
||||
*/
|
||||
static int smack_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
- const char *name)
|
||||
+ const char *name, struct file *file)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
@@ -703,7 +707,7 @@ static int smack_inode_removexattr(struc
|
||||
if (!capable(CAP_MAC_ADMIN))
|
||||
rc = -EPERM;
|
||||
} else
|
||||
- rc = cap_inode_removexattr(dentry, mnt, name);
|
||||
+ rc = cap_inode_removexattr(dentry, mnt, name, file);
|
||||
|
||||
if (rc == 0)
|
||||
rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
|
63
kernel-patches/2.6.28/series
Normal file
63
kernel-patches/2.6.28/series
Normal file
|
@ -0,0 +1,63 @@
|
|||
securit_default.diff
|
||||
security-create.diff
|
||||
remove_suid.diff
|
||||
vfs-notify_change.diff
|
||||
security-setattr.diff
|
||||
vfs-mkdir.diff
|
||||
security-mkdir.diff
|
||||
vfs-mknod.diff
|
||||
security-mknod.diff
|
||||
vfs-symlink.diff
|
||||
security-symlink.diff
|
||||
security-readlink.diff
|
||||
vfs-link.diff
|
||||
security-link.diff
|
||||
vfs-rmdir.diff
|
||||
security-rmdir.diff
|
||||
fix-vfs_rmdir.diff
|
||||
vfs-unlink.diff
|
||||
security-unlink.diff
|
||||
vfs-rename.diff
|
||||
security-rename.diff
|
||||
vfs-setxattr.diff
|
||||
security-setxattr.diff
|
||||
vfs-getxattr.diff
|
||||
security-getxattr.diff
|
||||
vfs-listxattr.diff
|
||||
security-listxattr.diff
|
||||
vfs-removexattr.diff
|
||||
security-removexattr.diff
|
||||
unambiguous-__d_path.diff
|
||||
d_namespace_path.diff
|
||||
fsetattr.diff
|
||||
fsetattr-reintro-ATTR_FILE.diff
|
||||
fsetattr-restore-ia_file.diff
|
||||
file-handle-ops.diff
|
||||
security-xattr-file.diff
|
||||
sysctl-pathname.diff
|
||||
add-security_path_permission
|
||||
add-path_permission.diff
|
||||
do_path_lookup-nameidata.diff
|
||||
apparmor-audit.diff
|
||||
apparmor-main.diff
|
||||
apparmor-lsm.diff
|
||||
apparmor-path_permission
|
||||
apparmor-module_interface.diff
|
||||
apparmor-misc.diff
|
||||
apparmor-intree.diff
|
||||
apparmor-network.diff
|
||||
apparmor-rlimits.diff
|
||||
apparmor-2.6.25.diff
|
||||
apparmor-ptrace-2.6.27.diff
|
||||
export-security_inode_permission-for-aufs
|
||||
|
||||
#aufs/aa-hack
|
||||
#aufs/aufs-fsetattr
|
||||
fix-security-param.diff
|
||||
fix-complain.diff
|
||||
fix-d_namespace_path.diff
|
||||
fork-tracking.diff
|
||||
mount-capability.diff
|
||||
fix-config.diff
|
||||
AppArmor-checkpatch.diff
|
||||
AppArmor-misc-cleanups.diff
|
111
kernel-patches/2.6.28/sysctl-pathname.diff
Normal file
111
kernel-patches/2.6.28/sysctl-pathname.diff
Normal file
|
@ -0,0 +1,111 @@
|
|||
From: Andreas Gruenbacher <agruen@suse.de>
|
||||
Subject: Factor out sysctl pathname code
|
||||
|
||||
Convert the selinux sysctl pathname computation code into a standalone
|
||||
function.
|
||||
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
Reviewed-by: James Morris <jmorris@namei.org>
|
||||
|
||||
---
|
||||
include/linux/sysctl.h | 2 ++
|
||||
kernel/sysctl.c | 27 +++++++++++++++++++++++++++
|
||||
security/selinux/hooks.c | 34 +++++-----------------------------
|
||||
3 files changed, 34 insertions(+), 29 deletions(-)
|
||||
|
||||
--- a/include/linux/sysctl.h
|
||||
+++ b/include/linux/sysctl.h
|
||||
@@ -996,6 +996,8 @@ extern int proc_doulongvec_minmax(struct
|
||||
extern int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int,
|
||||
struct file *, void __user *, size_t *, loff_t *);
|
||||
|
||||
+extern char *sysctl_pathname(ctl_table *, char *, int);
|
||||
+
|
||||
extern int do_sysctl (int __user *name, int nlen,
|
||||
void __user *oldval, size_t __user *oldlenp,
|
||||
void __user *newval, size_t newlen);
|
||||
--- a/kernel/sysctl.c
|
||||
+++ b/kernel/sysctl.c
|
||||
@@ -1528,6 +1528,33 @@ void register_sysctl_root(struct ctl_tab
|
||||
spin_unlock(&sysctl_lock);
|
||||
}
|
||||
|
||||
+char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen)
|
||||
+{
|
||||
+ if (buflen < 1)
|
||||
+ return NULL;
|
||||
+ buffer += --buflen;
|
||||
+ *buffer = '\0';
|
||||
+
|
||||
+ while (table) {
|
||||
+ int namelen = strlen(table->procname);
|
||||
+
|
||||
+ if (buflen < namelen + 1)
|
||||
+ return NULL;
|
||||
+ buflen -= namelen + 1;
|
||||
+ buffer -= namelen;
|
||||
+ memcpy(buffer, table->procname, namelen);
|
||||
+ *--buffer = '/';
|
||||
+ table = table->parent;
|
||||
+ }
|
||||
+ if (buflen < 4)
|
||||
+ return NULL;
|
||||
+ buffer -= 4;
|
||||
+ memcpy(buffer, "/sys", 4);
|
||||
+
|
||||
+ return buffer;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(sysctl_pathname);
|
||||
+
|
||||
#ifdef CONFIG_SYSCTL_SYSCALL
|
||||
/* Perform the actual read/write of a sysctl table entry. */
|
||||
static int do_sysctl_strategy(struct ctl_table_root *root,
|
||||
--- a/security/selinux/hooks.c
|
||||
+++ b/security/selinux/hooks.c
|
||||
@@ -1814,40 +1814,16 @@ static int selinux_capable(struct task_s
|
||||
|
||||
static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
|
||||
{
|
||||
- int buflen, rc;
|
||||
- char *buffer, *path, *end;
|
||||
+ char *buffer, *path;
|
||||
+ int rc = -ENOMEM;
|
||||
|
||||
- rc = -ENOMEM;
|
||||
buffer = (char *)__get_free_page(GFP_KERNEL);
|
||||
if (!buffer)
|
||||
goto out;
|
||||
|
||||
- buflen = PAGE_SIZE;
|
||||
- end = buffer+buflen;
|
||||
- *--end = '\0';
|
||||
- buflen--;
|
||||
- path = end-1;
|
||||
- *path = '/';
|
||||
- while (table) {
|
||||
- const char *name = table->procname;
|
||||
- size_t namelen = strlen(name);
|
||||
- buflen -= namelen + 1;
|
||||
- if (buflen < 0)
|
||||
- goto out_free;
|
||||
- end -= namelen;
|
||||
- memcpy(end, name, namelen);
|
||||
- *--end = '/';
|
||||
- path = end;
|
||||
- table = table->parent;
|
||||
- }
|
||||
- buflen -= 4;
|
||||
- if (buflen < 0)
|
||||
- goto out_free;
|
||||
- end -= 4;
|
||||
- memcpy(end, "/sys", 4);
|
||||
- path = end;
|
||||
- rc = security_genfs_sid("proc", path, tclass, sid);
|
||||
-out_free:
|
||||
+ path = sysctl_pathname(table, buffer, PAGE_SIZE);
|
||||
+ if (path)
|
||||
+ rc = security_genfs_sid("proc", path, tclass, sid);
|
||||
free_page((unsigned long)buffer);
|
||||
out:
|
||||
return rc;
|
258
kernel-patches/2.6.28/unambiguous-__d_path.diff
Normal file
258
kernel-patches/2.6.28/unambiguous-__d_path.diff
Normal file
|
@ -0,0 +1,258 @@
|
|||
From: Andreas Gruenbacher <agruen@suse.de>
|
||||
Subject: Fix __d_path() for lazy unmounts and make it unambiguous
|
||||
|
||||
First, when __d_path() hits a lazily unmounted mount point, it tries to prepend
|
||||
the name of the lazily unmounted dentry to the path name. It gets this wrong,
|
||||
and also overwrites the slash that separates the name from the following
|
||||
pathname component. This patch fixes that; if a process was in directory
|
||||
/foo/bar and /foo got lazily unmounted, the old result was ``foobar'' (note the
|
||||
missing slash), while the new result with this patch is ``foo/bar''.
|
||||
|
||||
Second, it isn't always possible to tell from the __d_path() result whether the
|
||||
specified root and rootmnt (i.e., the chroot) was reached. We need an
|
||||
unambiguous result for AppArmor at least though, so we make sure that paths
|
||||
will only start with a slash if the path leads all the way up to the root.
|
||||
|
||||
We also add a @fail_deleted argument, which allows to get rid of some of the
|
||||
mess in sys_getcwd().
|
||||
|
||||
This patch leaves getcwd() and d_path() as they were before for everything
|
||||
except for bind-mounted directories; for them, it reports ``/foo/bar'' instead
|
||||
of ``foobar'' in the example described above.
|
||||
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
|
||||
|
||||
---
|
||||
fs/dcache.c | 126 +++++++++++++++++++++++++++----------------------
|
||||
fs/seq_file.c | 4 -
|
||||
include/linux/dcache.h | 5 +
|
||||
3 files changed, 75 insertions(+), 60 deletions(-)
|
||||
|
||||
--- a/fs/dcache.c
|
||||
+++ b/fs/dcache.c
|
||||
@@ -1907,44 +1907,46 @@ static int prepend_name(char **buffer, i
|
||||
* @root: root vfsmnt/dentry (may be modified by this function)
|
||||
* @buffer: buffer to return value in
|
||||
* @buflen: buffer length
|
||||
+ * @flags: flags controling behavior of d_path
|
||||
*
|
||||
- * Convert a dentry into an ASCII path name. If the entry has been deleted
|
||||
- * the string " (deleted)" is appended. Note that this is ambiguous.
|
||||
- *
|
||||
- * Returns the buffer or an error code if the path was too long.
|
||||
- *
|
||||
- * "buflen" should be positive. Caller holds the dcache_lock.
|
||||
+ * Convert a dentry into an ASCII path name. If the entry has been deleted,
|
||||
+ * then if @flags has D_PATH_FAIL_DELETED set, ERR_PTR(-ENOENT) is returned.
|
||||
+ * Otherwise, the string " (deleted)" is appended. Note that this is ambiguous.
|
||||
*
|
||||
* If path is not reachable from the supplied root, then the value of
|
||||
- * root is changed (without modifying refcounts).
|
||||
+ * root is changed (without modifying refcounts). The path returned in this
|
||||
+ * case will be relative (i.e., it will not start with a slash).
|
||||
+ *
|
||||
+ * Returns the buffer or an error code if the path was too long.
|
||||
*/
|
||||
char *__d_path(const struct path *path, struct path *root,
|
||||
- char *buffer, int buflen)
|
||||
+ char *buffer, int buflen, int flags)
|
||||
{
|
||||
struct dentry *dentry = path->dentry;
|
||||
struct vfsmount *vfsmnt = path->mnt;
|
||||
- char *end = buffer + buflen;
|
||||
- char *retval;
|
||||
+ const unsigned char *name;
|
||||
+ int namelen;
|
||||
+
|
||||
+ buffer += buflen;
|
||||
+ prepend(&buffer, &buflen, "\0", 1);
|
||||
|
||||
spin_lock(&vfsmount_lock);
|
||||
- prepend(&end, &buflen, "\0", 1);
|
||||
- if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
|
||||
- (prepend(&end, &buflen, " (deleted)", 10) != 0))
|
||||
+ spin_lock(&dcache_lock);
|
||||
+ if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
|
||||
+ if (flags & D_PATH_FAIL_DELETED) {
|
||||
+ buffer = ERR_PTR(-ENOENT);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (prepend(&buffer, &buflen, " (deleted)", 10) != 0)
|
||||
goto Elong;
|
||||
-
|
||||
+ }
|
||||
if (buflen < 1)
|
||||
goto Elong;
|
||||
- /* Get '/' right */
|
||||
- retval = end-1;
|
||||
- *retval = '/';
|
||||
|
||||
- for (;;) {
|
||||
+ while (dentry != root->dentry || vfsmnt != root->mnt) {
|
||||
struct dentry * parent;
|
||||
|
||||
- if (dentry == root->dentry && vfsmnt == root->mnt)
|
||||
- break;
|
||||
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
|
||||
- /* Global root? */
|
||||
if (vfsmnt->mnt_parent == vfsmnt) {
|
||||
goto global_root;
|
||||
}
|
||||
@@ -1954,27 +1956,51 @@ char *__d_path(const struct path *path,
|
||||
}
|
||||
parent = dentry->d_parent;
|
||||
prefetch(parent);
|
||||
- if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) ||
|
||||
- (prepend(&end, &buflen, "/", 1) != 0))
|
||||
+ if ((prepend_name(&buffer, &buflen, &dentry->d_name) != 0) ||
|
||||
+ (prepend(&buffer, &buflen, "/", 1) != 0))
|
||||
goto Elong;
|
||||
- retval = end;
|
||||
dentry = parent;
|
||||
}
|
||||
+ /* Get '/' right. */
|
||||
+ if (*buffer != '/' && prepend(&buffer, &buflen, "/", 1))
|
||||
+ goto Elong;
|
||||
|
||||
out:
|
||||
+ spin_unlock(&dcache_lock);
|
||||
spin_unlock(&vfsmount_lock);
|
||||
- return retval;
|
||||
+ return buffer;
|
||||
|
||||
global_root:
|
||||
- retval += 1; /* hit the slash */
|
||||
- if (prepend_name(&retval, &buflen, &dentry->d_name) != 0)
|
||||
+ /*
|
||||
+ * We went past the (vfsmount, dentry) we were looking for and have
|
||||
+ * either hit a root dentry, a lazily unmounted dentry, an
|
||||
+ * unconnected dentry, or the file is on a pseudo filesystem.
|
||||
+ */
|
||||
+ namelen = dentry->d_name.len;
|
||||
+ name = dentry->d_name.name;
|
||||
+
|
||||
+ /*
|
||||
+ * If this is a root dentry, then overwrite the slash. This
|
||||
+ * will also DTRT with pseudo filesystems which have root
|
||||
+ * dentries named "foo:".
|
||||
+ */
|
||||
+ if (IS_ROOT(dentry) && *buffer == '/') {
|
||||
+ buffer++;
|
||||
+ buflen++;
|
||||
+ }
|
||||
+ if ((flags & D_PATH_DISCONNECT) && *name == '/') {
|
||||
+ /* Make sure we won't return a pathname starting with '/' */
|
||||
+ name++;
|
||||
+ namelen--;
|
||||
+ }
|
||||
+ if (prepend(&buffer, &buflen, name, namelen))
|
||||
goto Elong;
|
||||
root->mnt = vfsmnt;
|
||||
root->dentry = dentry;
|
||||
goto out;
|
||||
|
||||
Elong:
|
||||
- retval = ERR_PTR(-ENAMETOOLONG);
|
||||
+ buffer = ERR_PTR(-ENAMETOOLONG);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -2011,10 +2037,8 @@ char *d_path(const struct path *path, ch
|
||||
root = current->fs->root;
|
||||
path_get(&root);
|
||||
read_unlock(¤t->fs->lock);
|
||||
- spin_lock(&dcache_lock);
|
||||
tmp = root;
|
||||
- res = __d_path(path, &tmp, buf, buflen);
|
||||
- spin_unlock(&dcache_lock);
|
||||
+ res = __d_path(path, &tmp, buf, buflen, 0);
|
||||
path_put(&root);
|
||||
return res;
|
||||
}
|
||||
@@ -2097,9 +2121,9 @@ Elong:
|
||||
*/
|
||||
asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
|
||||
{
|
||||
- int error;
|
||||
- struct path pwd, root;
|
||||
- char *page = (char *) __get_free_page(GFP_USER);
|
||||
+ int error, len;
|
||||
+ struct path pwd, root, tmp;
|
||||
+ char *page = (char *) __get_free_page(GFP_USER), *cwd;
|
||||
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
@@ -2111,30 +2135,20 @@ asmlinkage long sys_getcwd(char __user *
|
||||
path_get(&root);
|
||||
read_unlock(¤t->fs->lock);
|
||||
|
||||
- error = -ENOENT;
|
||||
- /* Has the current directory has been unlinked? */
|
||||
- spin_lock(&dcache_lock);
|
||||
- if (IS_ROOT(pwd.dentry) || !d_unhashed(pwd.dentry)) {
|
||||
- unsigned long len;
|
||||
- struct path tmp = root;
|
||||
- char * cwd;
|
||||
-
|
||||
- cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE);
|
||||
- spin_unlock(&dcache_lock);
|
||||
-
|
||||
+ tmp = root;
|
||||
+ cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE, D_PATH_FAIL_DELETED);
|
||||
+ if (IS_ERR(cwd)) {
|
||||
error = PTR_ERR(cwd);
|
||||
- if (IS_ERR(cwd))
|
||||
- goto out;
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
- error = -ERANGE;
|
||||
- len = PAGE_SIZE + page - cwd;
|
||||
- if (len <= size) {
|
||||
- error = len;
|
||||
- if (copy_to_user(buf, cwd, len))
|
||||
- error = -EFAULT;
|
||||
- }
|
||||
- } else
|
||||
- spin_unlock(&dcache_lock);
|
||||
+ error = -ERANGE;
|
||||
+ len = PAGE_SIZE + page - cwd;
|
||||
+ if (len <= size) {
|
||||
+ error = len;
|
||||
+ if (copy_to_user(buf, cwd, len))
|
||||
+ error = -EFAULT;
|
||||
+ }
|
||||
|
||||
out:
|
||||
path_put(&pwd);
|
||||
--- a/fs/seq_file.c
|
||||
+++ b/fs/seq_file.c
|
||||
@@ -412,9 +412,7 @@ int seq_path_root(struct seq_file *m, st
|
||||
char *s = m->buf + m->count;
|
||||
char *p;
|
||||
|
||||
- spin_lock(&dcache_lock);
|
||||
- p = __d_path(path, root, s, m->size - m->count);
|
||||
- spin_unlock(&dcache_lock);
|
||||
+ p = __d_path(path, root, s, m->size - m->count, 0);
|
||||
err = PTR_ERR(p);
|
||||
if (!IS_ERR(p)) {
|
||||
s = mangle_path(s, p, esc);
|
||||
--- a/include/linux/dcache.h
|
||||
+++ b/include/linux/dcache.h
|
||||
@@ -300,9 +300,12 @@ extern int d_validate(struct dentry *, s
|
||||
/*
|
||||
* helper function for dentry_operations.d_dname() members
|
||||
*/
|
||||
+#define D_PATH_FAIL_DELETED 1
|
||||
+#define D_PATH_DISCONNECT 2
|
||||
extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
|
||||
|
||||
-extern char *__d_path(const struct path *path, struct path *root, char *, int);
|
||||
+extern char *__d_path(const struct path *path, struct path *root, char *, int,
|
||||
+ int);
|
||||
extern char *d_path(const struct path *, char *, int);
|
||||
extern char *dentry_path(struct dentry *, char *, int);
|
||||
|
191
kernel-patches/2.6.28/vfs-getxattr.diff
Normal file
191
kernel-patches/2.6.28/vfs-getxattr.diff
Normal file
|
@ -0,0 +1,191 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Add a struct vfsmount parameter to vfs_getxattr()
|
||||
|
||||
The vfsmount will be passed down to the LSM hook so that LSMs can compute
|
||||
pathnames.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/nfsd/nfs4xdr.c | 2 +-
|
||||
fs/nfsd/vfs.c | 21 ++++++++++++---------
|
||||
fs/xattr.c | 15 ++++++++-------
|
||||
include/linux/nfsd/nfsd.h | 3 ++-
|
||||
include/linux/xattr.h | 2 +-
|
||||
5 files changed, 24 insertions(+), 19 deletions(-)
|
||||
|
||||
--- a/fs/nfsd/nfs4xdr.c
|
||||
+++ b/fs/nfsd/nfs4xdr.c
|
||||
@@ -1458,7 +1458,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, s
|
||||
}
|
||||
if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT
|
||||
| FATTR4_WORD0_SUPPORTED_ATTRS)) {
|
||||
- err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
|
||||
+ err = nfsd4_get_nfs4_acl(rqstp, dentry, exp->ex_path.mnt, &acl);
|
||||
aclsupport = (err == 0);
|
||||
if (bmval0 & FATTR4_WORD0_ACL) {
|
||||
if (err == -EOPNOTSUPP)
|
||||
--- a/fs/nfsd/vfs.c
|
||||
+++ b/fs/nfsd/vfs.c
|
||||
@@ -407,12 +407,13 @@ out_nfserr:
|
||||
#if defined(CONFIG_NFSD_V2_ACL) || \
|
||||
defined(CONFIG_NFSD_V3_ACL) || \
|
||||
defined(CONFIG_NFSD_V4)
|
||||
-static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
|
||||
+static ssize_t nfsd_getxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ char *key, void **buf)
|
||||
{
|
||||
ssize_t buflen;
|
||||
ssize_t ret;
|
||||
|
||||
- buflen = vfs_getxattr(dentry, key, NULL, 0);
|
||||
+ buflen = vfs_getxattr(dentry, mnt, key, NULL, 0);
|
||||
if (buflen <= 0)
|
||||
return buflen;
|
||||
|
||||
@@ -420,7 +421,7 @@ static ssize_t nfsd_getxattr(struct dent
|
||||
if (!*buf)
|
||||
return -ENOMEM;
|
||||
|
||||
- ret = vfs_getxattr(dentry, key, *buf, buflen);
|
||||
+ ret = vfs_getxattr(dentry, mnt, key, *buf, buflen);
|
||||
if (ret < 0)
|
||||
kfree(*buf);
|
||||
return ret;
|
||||
@@ -504,13 +505,13 @@ out_nfserr:
|
||||
}
|
||||
|
||||
static struct posix_acl *
|
||||
-_get_posix_acl(struct dentry *dentry, char *key)
|
||||
+_get_posix_acl(struct dentry *dentry, struct vfsmount *mnt, char *key)
|
||||
{
|
||||
void *buf = NULL;
|
||||
struct posix_acl *pacl = NULL;
|
||||
int buflen;
|
||||
|
||||
- buflen = nfsd_getxattr(dentry, key, &buf);
|
||||
+ buflen = nfsd_getxattr(dentry, mnt, key, &buf);
|
||||
if (!buflen)
|
||||
buflen = -ENODATA;
|
||||
if (buflen <= 0)
|
||||
@@ -522,14 +523,15 @@ _get_posix_acl(struct dentry *dentry, ch
|
||||
}
|
||||
|
||||
int
|
||||
-nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_acl **acl)
|
||||
+nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, struct nfs4_acl **acl)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
int error = 0;
|
||||
struct posix_acl *pacl = NULL, *dpacl = NULL;
|
||||
unsigned int flags = 0;
|
||||
|
||||
- pacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_ACCESS);
|
||||
+ pacl = _get_posix_acl(dentry, mnt, POSIX_ACL_XATTR_ACCESS);
|
||||
if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA)
|
||||
pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
|
||||
if (IS_ERR(pacl)) {
|
||||
@@ -539,7 +541,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqst
|
||||
}
|
||||
|
||||
if (S_ISDIR(inode->i_mode)) {
|
||||
- dpacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_DEFAULT);
|
||||
+ dpacl = _get_posix_acl(dentry, mnt, POSIX_ACL_XATTR_DEFAULT);
|
||||
if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA)
|
||||
dpacl = NULL;
|
||||
else if (IS_ERR(dpacl)) {
|
||||
@@ -2159,7 +2161,8 @@ nfsd_get_posix_acl(struct svc_fh *fhp, i
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
- size = nfsd_getxattr(fhp->fh_dentry, name, &value);
|
||||
+ size = nfsd_getxattr(fhp->fh_dentry, fhp->fh_export->ex_path.mnt, name,
|
||||
+ &value);
|
||||
if (size < 0)
|
||||
return ERR_PTR(size);
|
||||
|
||||
--- a/fs/xattr.c
|
||||
+++ b/fs/xattr.c
|
||||
@@ -131,7 +131,8 @@ out_noalloc:
|
||||
EXPORT_SYMBOL_GPL(xattr_getsecurity);
|
||||
|
||||
ssize_t
|
||||
-vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
|
||||
+vfs_getxattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
|
||||
+ void *value, size_t size)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
int error;
|
||||
@@ -315,8 +316,8 @@ sys_fsetxattr(int fd, const char __user
|
||||
* Extended attribute GET operations
|
||||
*/
|
||||
static ssize_t
|
||||
-getxattr(struct dentry *d, const char __user *name, void __user *value,
|
||||
- size_t size)
|
||||
+getxattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name,
|
||||
+ void __user *value, size_t size)
|
||||
{
|
||||
ssize_t error;
|
||||
void *kvalue = NULL;
|
||||
@@ -336,7 +337,7 @@ getxattr(struct dentry *d, const char __
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
- error = vfs_getxattr(d, kname, kvalue, size);
|
||||
+ error = vfs_getxattr(dentry, mnt, kname, kvalue, size);
|
||||
if (error > 0) {
|
||||
if (size && copy_to_user(value, kvalue, error))
|
||||
error = -EFAULT;
|
||||
@@ -359,7 +360,7 @@ sys_getxattr(const char __user *pathname
|
||||
error = user_path(pathname, &path);
|
||||
if (error)
|
||||
return error;
|
||||
- error = getxattr(path.dentry, name, value, size);
|
||||
+ error = getxattr(path.dentry, path.mnt, name, value, size);
|
||||
path_put(&path);
|
||||
return error;
|
||||
}
|
||||
@@ -374,7 +375,7 @@ sys_lgetxattr(const char __user *pathnam
|
||||
error = user_lpath(pathname, &path);
|
||||
if (error)
|
||||
return error;
|
||||
- error = getxattr(path.dentry, name, value, size);
|
||||
+ error = getxattr(path.dentry, path.mnt, name, value, size);
|
||||
path_put(&path);
|
||||
return error;
|
||||
}
|
||||
@@ -389,7 +390,7 @@ sys_fgetxattr(int fd, const char __user
|
||||
if (!f)
|
||||
return error;
|
||||
audit_inode(NULL, f->f_path.dentry);
|
||||
- error = getxattr(f->f_path.dentry, name, value, size);
|
||||
+ error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size);
|
||||
fput(f);
|
||||
return error;
|
||||
}
|
||||
--- a/include/linux/nfsd/nfsd.h
|
||||
+++ b/include/linux/nfsd/nfsd.h
|
||||
@@ -86,7 +86,8 @@ __be32 nfsd_setattr(struct svc_rqst *,
|
||||
#ifdef CONFIG_NFSD_V4
|
||||
__be32 nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
|
||||
struct nfs4_acl *);
|
||||
-int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
|
||||
+int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *,
|
||||
+ struct vfsmount *mnt, struct nfs4_acl **);
|
||||
#endif /* CONFIG_NFSD_V4 */
|
||||
__be32 nfsd_create(struct svc_rqst *, struct svc_fh *,
|
||||
char *name, int len, struct iattr *attrs,
|
||||
--- a/include/linux/xattr.h
|
||||
+++ b/include/linux/xattr.h
|
||||
@@ -48,7 +48,7 @@ struct xattr_handler {
|
||||
};
|
||||
|
||||
ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
|
||||
-ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
|
||||
+ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, const char *, void *, size_t);
|
||||
ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
|
||||
int vfs_setxattr(struct dentry *, struct vfsmount *, const char *, const void *, size_t, int);
|
||||
int vfs_removexattr(struct dentry *, const char *);
|
91
kernel-patches/2.6.28/vfs-link.diff
Normal file
91
kernel-patches/2.6.28/vfs-link.diff
Normal file
|
@ -0,0 +1,91 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Add struct vfsmount parameters to vfs_link()
|
||||
|
||||
The vfsmount will be passed down to the LSM hook so that LSMs can compute
|
||||
pathnames.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/ecryptfs/inode.c | 9 +++++++--
|
||||
fs/namei.c | 6 ++++--
|
||||
fs/nfsd/vfs.c | 3 ++-
|
||||
include/linux/fs.h | 2 +-
|
||||
4 files changed, 14 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/fs/ecryptfs/inode.c
|
||||
+++ b/fs/ecryptfs/inode.c
|
||||
@@ -403,19 +403,24 @@ static int ecryptfs_link(struct dentry *
|
||||
struct dentry *new_dentry)
|
||||
{
|
||||
struct dentry *lower_old_dentry;
|
||||
+ struct vfsmount *lower_old_mnt;
|
||||
struct dentry *lower_new_dentry;
|
||||
+ struct vfsmount *lower_new_mnt;
|
||||
struct dentry *lower_dir_dentry;
|
||||
u64 file_size_save;
|
||||
int rc;
|
||||
|
||||
file_size_save = i_size_read(old_dentry->d_inode);
|
||||
lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
|
||||
+ lower_old_mnt = ecryptfs_dentry_to_lower_mnt(old_dentry);
|
||||
lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
|
||||
+ lower_new_mnt = ecryptfs_dentry_to_lower_mnt(new_dentry);
|
||||
dget(lower_old_dentry);
|
||||
dget(lower_new_dentry);
|
||||
lower_dir_dentry = lock_parent(lower_new_dentry);
|
||||
- rc = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
|
||||
- lower_new_dentry);
|
||||
+ rc = vfs_link(lower_old_dentry, lower_old_mnt,
|
||||
+ lower_dir_dentry->d_inode, lower_new_dentry,
|
||||
+ lower_new_mnt);
|
||||
if (rc || !lower_new_dentry->d_inode)
|
||||
goto out_lock;
|
||||
rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0);
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -2366,7 +2366,7 @@ asmlinkage long sys_symlink(const char _
|
||||
return sys_symlinkat(oldname, AT_FDCWD, newname);
|
||||
}
|
||||
|
||||
-int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
|
||||
+int vfs_link(struct dentry *old_dentry, struct vfsmount *old_mnt, struct inode *dir, struct dentry *new_dentry, struct vfsmount *new_mnt)
|
||||
{
|
||||
struct inode *inode = old_dentry->d_inode;
|
||||
int error;
|
||||
@@ -2445,7 +2445,9 @@ asmlinkage long sys_linkat(int olddfd, c
|
||||
error = mnt_want_write(nd.path.mnt);
|
||||
if (error)
|
||||
goto out_dput;
|
||||
- error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry);
|
||||
+ error = vfs_link(old_path.dentry, old_path.mnt,
|
||||
+ nd.path.dentry->d_inode,
|
||||
+ new_dentry, nd.path.mnt);
|
||||
mnt_drop_write(nd.path.mnt);
|
||||
out_dput:
|
||||
dput(new_dentry);
|
||||
--- a/fs/nfsd/vfs.c
|
||||
+++ b/fs/nfsd/vfs.c
|
||||
@@ -1625,7 +1625,8 @@ nfsd_link(struct svc_rqst *rqstp, struct
|
||||
err = nfserrno(host_err);
|
||||
goto out_dput;
|
||||
}
|
||||
- host_err = vfs_link(dold, dirp, dnew);
|
||||
+ host_err = vfs_link(dold, tfhp->fh_export->ex_path.mnt, dirp,
|
||||
+ dnew, ffhp->fh_export->ex_path.mnt);
|
||||
if (!host_err) {
|
||||
if (EX_ISSYNC(ffhp->fh_export)) {
|
||||
err = nfserrno(nfsd_sync_dir(ddir));
|
||||
--- a/include/linux/fs.h
|
||||
+++ b/include/linux/fs.h
|
||||
@@ -1208,7 +1208,7 @@ extern int vfs_create(struct inode *, st
|
||||
extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int);
|
||||
extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t);
|
||||
extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *);
|
||||
-extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
|
||||
+extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
|
||||
extern int vfs_rmdir(struct inode *, struct dentry *);
|
||||
extern int vfs_unlink(struct inode *, struct dentry *);
|
||||
extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
|
101
kernel-patches/2.6.28/vfs-listxattr.diff
Normal file
101
kernel-patches/2.6.28/vfs-listxattr.diff
Normal file
|
@ -0,0 +1,101 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Add a struct vfsmount parameter to vfs_listxattr()
|
||||
|
||||
The vfsmount will be passed down to the LSM hook so that LSMs can compute
|
||||
pathnames.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/xattr.c | 25 ++++++++++++++-----------
|
||||
include/linux/xattr.h | 2 +-
|
||||
2 files changed, 15 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/fs/xattr.c
|
||||
+++ b/fs/xattr.c
|
||||
@@ -168,18 +168,20 @@ nolsm:
|
||||
EXPORT_SYMBOL_GPL(vfs_getxattr);
|
||||
|
||||
ssize_t
|
||||
-vfs_listxattr(struct dentry *d, char *list, size_t size)
|
||||
+vfs_listxattr(struct dentry *dentry, struct vfsmount *mnt, char *list,
|
||||
+ size_t size)
|
||||
{
|
||||
+ struct inode *inode = dentry->d_inode;
|
||||
ssize_t error;
|
||||
|
||||
- error = security_inode_listxattr(d);
|
||||
+ error = security_inode_listxattr(dentry);
|
||||
if (error)
|
||||
return error;
|
||||
error = -EOPNOTSUPP;
|
||||
- if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
|
||||
- error = d->d_inode->i_op->listxattr(d, list, size);
|
||||
- } else {
|
||||
- error = security_inode_listsecurity(d->d_inode, list, size);
|
||||
+ if (inode->i_op && inode->i_op->listxattr)
|
||||
+ error = inode->i_op->listxattr(dentry, list, size);
|
||||
+ else {
|
||||
+ error = security_inode_listsecurity(inode, list, size);
|
||||
if (size && error > size)
|
||||
error = -ERANGE;
|
||||
}
|
||||
@@ -399,7 +401,8 @@ sys_fgetxattr(int fd, const char __user
|
||||
* Extended attribute LIST operations
|
||||
*/
|
||||
static ssize_t
|
||||
-listxattr(struct dentry *d, char __user *list, size_t size)
|
||||
+listxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *list,
|
||||
+ size_t size)
|
||||
{
|
||||
ssize_t error;
|
||||
char *klist = NULL;
|
||||
@@ -412,7 +415,7 @@ listxattr(struct dentry *d, char __user
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
- error = vfs_listxattr(d, klist, size);
|
||||
+ error = vfs_listxattr(dentry, mnt, klist, size);
|
||||
if (error > 0) {
|
||||
if (size && copy_to_user(list, klist, error))
|
||||
error = -EFAULT;
|
||||
@@ -434,7 +437,7 @@ sys_listxattr(const char __user *pathnam
|
||||
error = user_path(pathname, &path);
|
||||
if (error)
|
||||
return error;
|
||||
- error = listxattr(path.dentry, list, size);
|
||||
+ error = listxattr(path.dentry, path.mnt, list, size);
|
||||
path_put(&path);
|
||||
return error;
|
||||
}
|
||||
@@ -448,7 +451,7 @@ sys_llistxattr(const char __user *pathna
|
||||
error = user_lpath(pathname, &path);
|
||||
if (error)
|
||||
return error;
|
||||
- error = listxattr(path.dentry, list, size);
|
||||
+ error = listxattr(path.dentry, path.mnt, list, size);
|
||||
path_put(&path);
|
||||
return error;
|
||||
}
|
||||
@@ -463,7 +466,7 @@ sys_flistxattr(int fd, char __user *list
|
||||
if (!f)
|
||||
return error;
|
||||
audit_inode(NULL, f->f_path.dentry);
|
||||
- error = listxattr(f->f_path.dentry, list, size);
|
||||
+ error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size);
|
||||
fput(f);
|
||||
return error;
|
||||
}
|
||||
--- a/include/linux/xattr.h
|
||||
+++ b/include/linux/xattr.h
|
||||
@@ -49,7 +49,7 @@ struct xattr_handler {
|
||||
|
||||
ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
|
||||
ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, const char *, void *, size_t);
|
||||
-ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
|
||||
+ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list, size_t size);
|
||||
int vfs_setxattr(struct dentry *, struct vfsmount *, const char *, const void *, size_t, int);
|
||||
int vfs_removexattr(struct dentry *, const char *);
|
||||
|
137
kernel-patches/2.6.28/vfs-mkdir.diff
Normal file
137
kernel-patches/2.6.28/vfs-mkdir.diff
Normal file
|
@ -0,0 +1,137 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Add struct vfsmount parameter to vfs_mkdir()
|
||||
|
||||
The vfsmount will be passed down to the LSM hook so that LSMs can compute
|
||||
pathnames.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/ecryptfs/inode.c | 5 ++++-
|
||||
fs/namei.c | 5 +++--
|
||||
fs/nfsd/nfs4recover.c | 3 ++-
|
||||
fs/nfsd/vfs.c | 8 +++++---
|
||||
include/linux/fs.h | 2 +-
|
||||
kernel/cgroup.c | 2 +-
|
||||
6 files changed, 16 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/fs/ecryptfs/inode.c
|
||||
+++ b/fs/ecryptfs/inode.c
|
||||
@@ -501,11 +501,14 @@ static int ecryptfs_mkdir(struct inode *
|
||||
{
|
||||
int rc;
|
||||
struct dentry *lower_dentry;
|
||||
+ struct vfsmount *lower_mnt;
|
||||
struct dentry *lower_dir_dentry;
|
||||
|
||||
lower_dentry = ecryptfs_dentry_to_lower(dentry);
|
||||
+ lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
|
||||
lower_dir_dentry = lock_parent(lower_dentry);
|
||||
- rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, mode);
|
||||
+ rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, lower_mnt,
|
||||
+ mode);
|
||||
if (rc || !lower_dentry->d_inode)
|
||||
goto out;
|
||||
rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -2025,7 +2025,8 @@ asmlinkage long sys_mknod(const char __u
|
||||
return sys_mknodat(AT_FDCWD, filename, mode, dev);
|
||||
}
|
||||
|
||||
-int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
||||
+int vfs_mkdir(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ int mode)
|
||||
{
|
||||
int error = may_create(dir, dentry);
|
||||
|
||||
@@ -2068,7 +2069,7 @@ asmlinkage long sys_mkdirat(int dfd, con
|
||||
error = mnt_want_write(nd.path.mnt);
|
||||
if (error)
|
||||
goto out_dput;
|
||||
- error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
|
||||
+ error = vfs_mkdir(nd.path.dentry->d_inode, dentry, nd.path.mnt, mode);
|
||||
mnt_drop_write(nd.path.mnt);
|
||||
out_dput:
|
||||
dput(dentry);
|
||||
--- a/fs/nfsd/nfs4recover.c
|
||||
+++ b/fs/nfsd/nfs4recover.c
|
||||
@@ -158,7 +158,8 @@ nfsd4_create_clid_dir(struct nfs4_client
|
||||
status = mnt_want_write(rec_dir.mnt);
|
||||
if (status)
|
||||
goto out_put;
|
||||
- status = vfs_mkdir(rec_dir.dentry->d_inode, dentry, S_IRWXU);
|
||||
+ status = vfs_mkdir(rec_dir.dentry->d_inode, dentry, rec_dir.mnt,
|
||||
+ S_IRWXU);
|
||||
mnt_drop_write(rec_dir.mnt);
|
||||
out_put:
|
||||
dput(dentry);
|
||||
--- a/fs/nfsd/vfs.c
|
||||
+++ b/fs/nfsd/vfs.c
|
||||
@@ -1190,6 +1190,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
|
||||
int type, dev_t rdev, struct svc_fh *resfhp)
|
||||
{
|
||||
struct dentry *dentry, *dchild = NULL;
|
||||
+ struct svc_export *exp;
|
||||
struct inode *dirp;
|
||||
__be32 err;
|
||||
__be32 err2;
|
||||
@@ -1207,6 +1208,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
|
||||
goto out;
|
||||
|
||||
dentry = fhp->fh_dentry;
|
||||
+ exp = fhp->fh_export;
|
||||
dirp = dentry->d_inode;
|
||||
|
||||
err = nfserr_notdir;
|
||||
@@ -1223,7 +1225,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
|
||||
host_err = PTR_ERR(dchild);
|
||||
if (IS_ERR(dchild))
|
||||
goto out_nfserr;
|
||||
- err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
|
||||
+ err = fh_compose(resfhp, exp, dchild, fhp);
|
||||
if (err)
|
||||
goto out;
|
||||
} else {
|
||||
@@ -1273,7 +1275,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
|
||||
host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
|
||||
break;
|
||||
case S_IFDIR:
|
||||
- host_err = vfs_mkdir(dirp, dchild, iap->ia_mode);
|
||||
+ host_err = vfs_mkdir(dirp, dchild, exp->ex_path.mnt, iap->ia_mode);
|
||||
break;
|
||||
case S_IFCHR:
|
||||
case S_IFBLK:
|
||||
@@ -1287,7 +1289,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
|
||||
goto out_nfserr;
|
||||
}
|
||||
|
||||
- if (EX_ISSYNC(fhp->fh_export)) {
|
||||
+ if (EX_ISSYNC(exp)) {
|
||||
err = nfserrno(nfsd_sync_dir(dentry));
|
||||
write_inode_now(dchild->d_inode, 1);
|
||||
}
|
||||
--- a/include/linux/fs.h
|
||||
+++ b/include/linux/fs.h
|
||||
@@ -1205,7 +1205,7 @@ extern void unlock_super(struct super_bl
|
||||
*/
|
||||
extern int vfs_permission(struct nameidata *, int);
|
||||
extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *);
|
||||
-extern int vfs_mkdir(struct inode *, struct dentry *, int);
|
||||
+extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int);
|
||||
extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t);
|
||||
extern int vfs_symlink(struct inode *, struct dentry *, const char *);
|
||||
extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
|
||||
--- a/kernel/cgroup.c
|
||||
+++ b/kernel/cgroup.c
|
||||
@@ -2966,7 +2966,7 @@ int cgroup_clone(struct task_struct *tsk
|
||||
}
|
||||
|
||||
/* Create the cgroup directory, which also creates the cgroup */
|
||||
- ret = vfs_mkdir(inode, dentry, S_IFDIR | 0755);
|
||||
+ ret = vfs_mkdir(inode, dentry, NULL, S_IFDIR | 0755);
|
||||
child = __d_cgrp(dentry);
|
||||
dput(dentry);
|
||||
if (ret) {
|
99
kernel-patches/2.6.28/vfs-mknod.diff
Normal file
99
kernel-patches/2.6.28/vfs-mknod.diff
Normal file
|
@ -0,0 +1,99 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Add a struct vfsmount parameter to vfs_mknod()
|
||||
|
||||
The vfsmount will be passed down to the LSM hook so that LSMs can compute
|
||||
pathnames.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/ecryptfs/inode.c | 5 ++++-
|
||||
fs/namei.c | 10 ++++++----
|
||||
fs/nfsd/vfs.c | 3 ++-
|
||||
include/linux/fs.h | 2 +-
|
||||
net/unix/af_unix.c | 3 ++-
|
||||
5 files changed, 15 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/fs/ecryptfs/inode.c
|
||||
+++ b/fs/ecryptfs/inode.c
|
||||
@@ -552,11 +552,14 @@ ecryptfs_mknod(struct inode *dir, struct
|
||||
{
|
||||
int rc;
|
||||
struct dentry *lower_dentry;
|
||||
+ struct vfsmount *lower_mnt;
|
||||
struct dentry *lower_dir_dentry;
|
||||
|
||||
lower_dentry = ecryptfs_dentry_to_lower(dentry);
|
||||
+ lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
|
||||
lower_dir_dentry = lock_parent(lower_dentry);
|
||||
- rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, mode, dev);
|
||||
+ rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, lower_mnt, mode,
|
||||
+ dev);
|
||||
if (rc || !lower_dentry->d_inode)
|
||||
goto out;
|
||||
rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -1924,7 +1924,8 @@ fail:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lookup_create);
|
||||
|
||||
-int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
|
||||
+int vfs_mknod(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ int mode, dev_t dev)
|
||||
{
|
||||
int error = may_create(dir, dentry);
|
||||
|
||||
@@ -2002,11 +2003,12 @@ asmlinkage long sys_mknodat(int dfd, con
|
||||
error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd);
|
||||
break;
|
||||
case S_IFCHR: case S_IFBLK:
|
||||
- error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,
|
||||
- new_decode_dev(dev));
|
||||
+ error = vfs_mknod(nd.path.dentry->d_inode, dentry,
|
||||
+ nd.path, mode, new_decode_dev(dev));
|
||||
break;
|
||||
case S_IFIFO: case S_IFSOCK:
|
||||
- error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0);
|
||||
+ error = vfs_mknod(nd.path.dentry->d_inode, dentry,
|
||||
+ nd.path, mode, 0);
|
||||
break;
|
||||
}
|
||||
mnt_drop_write(nd.path.mnt);
|
||||
--- a/fs/nfsd/vfs.c
|
||||
+++ b/fs/nfsd/vfs.c
|
||||
@@ -1281,7 +1281,8 @@ nfsd_create(struct svc_rqst *rqstp, stru
|
||||
case S_IFBLK:
|
||||
case S_IFIFO:
|
||||
case S_IFSOCK:
|
||||
- host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
|
||||
+ host_err = vfs_mknod(dirp, dchild, exp->ex_path.mnt,
|
||||
+ iap->ia_mode, rdev);
|
||||
break;
|
||||
}
|
||||
if (host_err < 0) {
|
||||
--- a/include/linux/fs.h
|
||||
+++ b/include/linux/fs.h
|
||||
@@ -1206,7 +1206,7 @@ extern void unlock_super(struct super_bl
|
||||
extern int vfs_permission(struct nameidata *, int);
|
||||
extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *);
|
||||
extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int);
|
||||
-extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t);
|
||||
+extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t);
|
||||
extern int vfs_symlink(struct inode *, struct dentry *, const char *);
|
||||
extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
|
||||
extern int vfs_rmdir(struct inode *, struct dentry *);
|
||||
--- a/net/unix/af_unix.c
|
||||
+++ b/net/unix/af_unix.c
|
||||
@@ -829,7 +829,8 @@ static int unix_bind(struct socket *sock
|
||||
err = mnt_want_write(nd.path.mnt);
|
||||
if (err)
|
||||
goto out_mknod_dput;
|
||||
- err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
|
||||
+ err = vfs_mknod(nd.path.dentry->d_inode, dentry, nd.path.mnt,
|
||||
+ mode, 0);
|
||||
mnt_drop_write(nd.path.mnt);
|
||||
if (err)
|
||||
goto out_mknod_dput;
|
321
kernel-patches/2.6.28/vfs-notify_change.diff
Normal file
321
kernel-patches/2.6.28/vfs-notify_change.diff
Normal file
|
@ -0,0 +1,321 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Add a vfsmount parameter to notify_change()
|
||||
|
||||
The vfsmount parameter must be set appropriately for files visibile
|
||||
outside the kernel. Files that are only used in a filesystem (e.g.,
|
||||
reiserfs xattr files) will have a NULL vfsmount.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/attr.c | 3 ++-
|
||||
fs/ecryptfs/inode.c | 4 +++-
|
||||
fs/exec.c | 3 ++-
|
||||
fs/hpfs/namei.c | 2 +-
|
||||
fs/namei.c | 2 +-
|
||||
fs/nfsd/vfs.c | 8 ++++----
|
||||
fs/open.c | 28 +++++++++++++++-------------
|
||||
fs/reiserfs/xattr.c | 6 +++---
|
||||
fs/utimes.c | 2 +-
|
||||
include/linux/fs.h | 6 +++---
|
||||
mm/filemap.c | 2 +-
|
||||
11 files changed, 36 insertions(+), 30 deletions(-)
|
||||
|
||||
--- a/fs/attr.c
|
||||
+++ b/fs/attr.c
|
||||
@@ -100,7 +100,8 @@ int inode_setattr(struct inode * inode,
|
||||
}
|
||||
EXPORT_SYMBOL(inode_setattr);
|
||||
|
||||
-int notify_change(struct dentry * dentry, struct iattr * attr)
|
||||
+int notify_change(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ struct iattr *attr)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
mode_t mode = inode->i_mode;
|
||||
--- a/fs/ecryptfs/inode.c
|
||||
+++ b/fs/ecryptfs/inode.c
|
||||
@@ -849,6 +849,7 @@ static int ecryptfs_setattr(struct dentr
|
||||
{
|
||||
int rc = 0;
|
||||
struct dentry *lower_dentry;
|
||||
+ struct vfsmount *lower_mnt;
|
||||
struct inode *inode;
|
||||
struct inode *lower_inode;
|
||||
struct ecryptfs_crypt_stat *crypt_stat;
|
||||
@@ -859,6 +860,7 @@ static int ecryptfs_setattr(struct dentr
|
||||
inode = dentry->d_inode;
|
||||
lower_inode = ecryptfs_inode_to_lower(inode);
|
||||
lower_dentry = ecryptfs_dentry_to_lower(dentry);
|
||||
+ lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
|
||||
mutex_lock(&crypt_stat->cs_mutex);
|
||||
if (S_ISDIR(dentry->d_inode->i_mode))
|
||||
crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
|
||||
@@ -910,7 +912,7 @@ static int ecryptfs_setattr(struct dentr
|
||||
ia->ia_valid &= ~ATTR_MODE;
|
||||
|
||||
mutex_lock(&lower_dentry->d_inode->i_mutex);
|
||||
- rc = notify_change(lower_dentry, ia);
|
||||
+ rc = notify_change(lower_dentry, lower_mnt, ia);
|
||||
mutex_unlock(&lower_dentry->d_inode->i_mutex);
|
||||
out:
|
||||
fsstack_copy_attr_all(inode, lower_inode, NULL);
|
||||
--- a/fs/exec.c
|
||||
+++ b/fs/exec.c
|
||||
@@ -1821,7 +1821,8 @@ int do_coredump(long signr, int exit_cod
|
||||
goto close_fail;
|
||||
if (!file->f_op->write)
|
||||
goto close_fail;
|
||||
- if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0)
|
||||
+ if (!ispipe &&
|
||||
+ do_truncate(file->f_path.dentry, file->f_path.mnt, 0, 0, file) != 0)
|
||||
goto close_fail;
|
||||
|
||||
retval = binfmt->core_dump(signr, regs, file, core_limit);
|
||||
--- a/fs/hpfs/namei.c
|
||||
+++ b/fs/hpfs/namei.c
|
||||
@@ -426,7 +426,7 @@ again:
|
||||
/*printk("HPFS: truncating file before delete.\n");*/
|
||||
newattrs.ia_size = 0;
|
||||
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
|
||||
- err = notify_change(dentry, &newattrs);
|
||||
+ err = notify_change(dentry, NULL, &newattrs);
|
||||
put_write_access(inode);
|
||||
if (!err)
|
||||
goto again;
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -1557,7 +1557,7 @@ int may_open(struct nameidata *nd, int a
|
||||
if (!error) {
|
||||
DQUOT_INIT(inode);
|
||||
|
||||
- error = do_truncate(dentry, 0,
|
||||
+ error = do_truncate(dentry, nd->path.mnt, 0,
|
||||
ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
|
||||
NULL);
|
||||
}
|
||||
--- a/fs/nfsd/vfs.c
|
||||
+++ b/fs/nfsd/vfs.c
|
||||
@@ -387,7 +387,7 @@ nfsd_setattr(struct svc_rqst *rqstp, str
|
||||
err = nfserr_notsync;
|
||||
if (!check_guard || guardtime == inode->i_ctime.tv_sec) {
|
||||
fh_lock(fhp);
|
||||
- host_err = notify_change(dentry, iap);
|
||||
+ host_err = notify_change(dentry, fhp->fh_export->ex_path.mnt, iap);
|
||||
err = nfserrno(host_err);
|
||||
fh_unlock(fhp);
|
||||
}
|
||||
@@ -947,13 +947,13 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
-static void kill_suid(struct dentry *dentry)
|
||||
+static void kill_suid(struct dentry *dentry, struct vfsmount *mnt)
|
||||
{
|
||||
struct iattr ia;
|
||||
ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
|
||||
|
||||
mutex_lock(&dentry->d_inode->i_mutex);
|
||||
- notify_change(dentry, &ia);
|
||||
+ notify_change(dentry, mnt, &ia);
|
||||
mutex_unlock(&dentry->d_inode->i_mutex);
|
||||
}
|
||||
|
||||
@@ -1012,7 +1012,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s
|
||||
|
||||
/* clear setuid/setgid flag after write */
|
||||
if (host_err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID)))
|
||||
- kill_suid(dentry);
|
||||
+ kill_suid(dentry, exp->ex_path.mnt);
|
||||
|
||||
if (host_err >= 0 && stable) {
|
||||
static ino_t last_ino;
|
||||
--- a/fs/open.c
|
||||
+++ b/fs/open.c
|
||||
@@ -197,8 +197,8 @@ out:
|
||||
return error;
|
||||
}
|
||||
|
||||
-int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
|
||||
- struct file *filp)
|
||||
+int do_truncate(struct dentry *dentry, struct vfsmount *mnt, loff_t length,
|
||||
+ unsigned int time_attrs, struct file *filp)
|
||||
{
|
||||
int err;
|
||||
struct iattr newattrs;
|
||||
@@ -218,7 +218,7 @@ int do_truncate(struct dentry *dentry, l
|
||||
newattrs.ia_valid |= should_remove_suid(dentry);
|
||||
|
||||
mutex_lock(&dentry->d_inode->i_mutex);
|
||||
- err = notify_change(dentry, &newattrs);
|
||||
+ err = notify_change(dentry, mnt, &newattrs);
|
||||
mutex_unlock(&dentry->d_inode->i_mutex);
|
||||
return err;
|
||||
}
|
||||
@@ -274,7 +274,7 @@ static long do_sys_truncate(const char _
|
||||
error = locks_verify_truncate(inode, NULL, length);
|
||||
if (!error) {
|
||||
DQUOT_INIT(inode);
|
||||
- error = do_truncate(path.dentry, length, 0, NULL);
|
||||
+ error = do_truncate(path.dentry, path.mnt, length, 0, NULL);
|
||||
}
|
||||
|
||||
put_write_and_out:
|
||||
@@ -329,7 +329,8 @@ static long do_sys_ftruncate(unsigned in
|
||||
|
||||
error = locks_verify_truncate(inode, file, length);
|
||||
if (!error)
|
||||
- error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file);
|
||||
+ error = do_truncate(dentry, file->f_path.mnt, length,
|
||||
+ ATTR_MTIME|ATTR_CTIME, file);
|
||||
out_putf:
|
||||
fput(file);
|
||||
out:
|
||||
@@ -605,7 +606,7 @@ asmlinkage long sys_fchmod(unsigned int
|
||||
mode = inode->i_mode;
|
||||
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
|
||||
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
|
||||
- err = notify_change(dentry, &newattrs);
|
||||
+ err = notify_change(dentry, file->f_path.mnt, &newattrs);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
mnt_drop_write(file->f_path.mnt);
|
||||
out_putf:
|
||||
@@ -635,7 +636,7 @@ asmlinkage long sys_fchmodat(int dfd, co
|
||||
mode = inode->i_mode;
|
||||
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
|
||||
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
|
||||
- error = notify_change(path.dentry, &newattrs);
|
||||
+ error = notify_change(path.dentry, path.mnt, &newattrs);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
mnt_drop_write(path.mnt);
|
||||
dput_and_out:
|
||||
@@ -649,7 +650,8 @@ asmlinkage long sys_chmod(const char __u
|
||||
return sys_fchmodat(AT_FDCWD, filename, mode);
|
||||
}
|
||||
|
||||
-static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
|
||||
+static int chown_common(struct dentry * dentry, struct vfsmount *mnt,
|
||||
+ uid_t user, gid_t group)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
int error;
|
||||
@@ -668,7 +670,7 @@ static int chown_common(struct dentry *
|
||||
newattrs.ia_valid |=
|
||||
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
|
||||
mutex_lock(&inode->i_mutex);
|
||||
- error = notify_change(dentry, &newattrs);
|
||||
+ error = notify_change(dentry, mnt, &newattrs);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
||||
return error;
|
||||
@@ -685,7 +687,7 @@ asmlinkage long sys_chown(const char __u
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (error)
|
||||
goto out_release;
|
||||
- error = chown_common(path.dentry, user, group);
|
||||
+ error = chown_common(path.dentry, path.mnt, user, group);
|
||||
mnt_drop_write(path.mnt);
|
||||
out_release:
|
||||
path_put(&path);
|
||||
@@ -710,7 +712,7 @@ asmlinkage long sys_fchownat(int dfd, co
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (error)
|
||||
goto out_release;
|
||||
- error = chown_common(path.dentry, user, group);
|
||||
+ error = chown_common(path.dentry, path.mnt, user, group);
|
||||
mnt_drop_write(path.mnt);
|
||||
out_release:
|
||||
path_put(&path);
|
||||
@@ -729,7 +731,7 @@ asmlinkage long sys_lchown(const char __
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (error)
|
||||
goto out_release;
|
||||
- error = chown_common(path.dentry, user, group);
|
||||
+ error = chown_common(path.dentry, path.mnt, user, group);
|
||||
mnt_drop_write(path.mnt);
|
||||
out_release:
|
||||
path_put(&path);
|
||||
@@ -753,7 +755,7 @@ asmlinkage long sys_fchown(unsigned int
|
||||
goto out_fput;
|
||||
dentry = file->f_path.dentry;
|
||||
audit_inode(NULL, dentry);
|
||||
- error = chown_common(dentry, user, group);
|
||||
+ error = chown_common(dentry, file->f_path.mnt, user, group);
|
||||
mnt_drop_write(file->f_path.mnt);
|
||||
out_fput:
|
||||
fput(file);
|
||||
--- a/fs/reiserfs/xattr.c
|
||||
+++ b/fs/reiserfs/xattr.c
|
||||
@@ -459,7 +459,7 @@ reiserfs_xattr_set(struct inode *inode,
|
||||
newattrs.ia_size = buffer_size;
|
||||
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
|
||||
mutex_lock_nested(&xinode->i_mutex, I_MUTEX_XATTR);
|
||||
- err = notify_change(dentry, &newattrs);
|
||||
+ err = notify_change(dentry, NULL, &newattrs);
|
||||
if (err)
|
||||
goto out_filp;
|
||||
|
||||
@@ -790,7 +790,7 @@ reiserfs_chown_xattrs_filler(void *buf,
|
||||
}
|
||||
|
||||
if (!S_ISDIR(xafile->d_inode->i_mode))
|
||||
- err = notify_change(xafile, attrs);
|
||||
+ err = notify_change(xafile, NULL, attrs);
|
||||
dput(xafile);
|
||||
|
||||
return err;
|
||||
@@ -834,7 +834,7 @@ int reiserfs_chown_xattrs(struct inode *
|
||||
goto out_dir;
|
||||
}
|
||||
|
||||
- err = notify_change(dir, attrs);
|
||||
+ err = notify_change(dir, NULL, attrs);
|
||||
unlock_kernel();
|
||||
|
||||
out_dir:
|
||||
--- a/fs/utimes.c
|
||||
+++ b/fs/utimes.c
|
||||
@@ -102,7 +102,7 @@ static int utimes_common(struct path *pa
|
||||
}
|
||||
}
|
||||
mutex_lock(&inode->i_mutex);
|
||||
- error = notify_change(path->dentry, &newattrs);
|
||||
+ error = notify_change(path->dentry, path->mnt, &newattrs);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
||||
mnt_drop_write_and_out:
|
||||
--- a/include/linux/fs.h
|
||||
+++ b/include/linux/fs.h
|
||||
@@ -1669,8 +1669,8 @@ static inline int break_lease(struct ino
|
||||
|
||||
/* fs/open.c */
|
||||
|
||||
-extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
|
||||
- struct file *filp);
|
||||
+extern int do_truncate(struct dentry *, struct vfsmount *, loff_t start,
|
||||
+ unsigned int time_attrs, struct file *filp);
|
||||
extern long do_sys_open(int dfd, const char __user *filename, int flags,
|
||||
int mode);
|
||||
extern struct file *filp_open(const char *, int, int);
|
||||
@@ -1830,7 +1830,7 @@ extern int do_remount_sb(struct super_bl
|
||||
#ifdef CONFIG_BLOCK
|
||||
extern sector_t bmap(struct inode *, sector_t);
|
||||
#endif
|
||||
-extern int notify_change(struct dentry *, struct iattr *);
|
||||
+extern int notify_change(struct dentry *, struct vfsmount *, struct iattr *);
|
||||
extern int inode_permission(struct inode *, int);
|
||||
extern int generic_permission(struct inode *, int,
|
||||
int (*check_acl)(struct inode *, int));
|
||||
--- a/mm/filemap.c
|
||||
+++ b/mm/filemap.c
|
||||
@@ -1778,7 +1778,7 @@ static int __remove_suid(struct path *pa
|
||||
struct iattr newattrs;
|
||||
|
||||
newattrs.ia_valid = ATTR_FORCE | kill;
|
||||
- return notify_change(path->dentry, &newattrs);
|
||||
+ return notify_change(path->dentry, path->mnt, &newattrs);
|
||||
}
|
||||
|
||||
int file_remove_suid(struct file *file)
|
121
kernel-patches/2.6.28/vfs-removexattr.diff
Normal file
121
kernel-patches/2.6.28/vfs-removexattr.diff
Normal file
|
@ -0,0 +1,121 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Add a struct vfsmount parameter to vfs_removexattr()
|
||||
|
||||
The vfsmount will be passed down to the LSM hook so that LSMs can compute
|
||||
pathnames.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/nfsd/vfs.c | 11 ++++++-----
|
||||
fs/xattr.c | 12 ++++++------
|
||||
include/linux/xattr.h | 2 +-
|
||||
3 files changed, 13 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/fs/nfsd/vfs.c
|
||||
+++ b/fs/nfsd/vfs.c
|
||||
@@ -2174,6 +2174,7 @@ nfsd_get_posix_acl(struct svc_fh *fhp, i
|
||||
int
|
||||
nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
|
||||
{
|
||||
+ struct vfsmount *mnt;
|
||||
struct inode *inode = fhp->fh_dentry->d_inode;
|
||||
char *name;
|
||||
void *value = NULL;
|
||||
@@ -2206,22 +2207,22 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
|
||||
} else
|
||||
size = 0;
|
||||
|
||||
- error = mnt_want_write(fhp->fh_export->ex_path.mnt);
|
||||
+ mnt = fhp->fh_export->ex_path.mnt;
|
||||
+ error = mnt_want_write(mnt);
|
||||
if (error)
|
||||
goto getout;
|
||||
if (size)
|
||||
- error = vfs_setxattr(fhp->fh_dentry, fhp->fh_export->ex_path.mnt,
|
||||
- name, value, size,0);
|
||||
+ error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size,0);
|
||||
else {
|
||||
if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
|
||||
error = 0;
|
||||
else {
|
||||
- error = vfs_removexattr(fhp->fh_dentry, name);
|
||||
+ error = vfs_removexattr(fhp->fh_dentry, mnt, name);
|
||||
if (error == -ENODATA)
|
||||
error = 0;
|
||||
}
|
||||
}
|
||||
- mnt_drop_write(fhp->fh_export->ex_path.mnt);
|
||||
+ mnt_drop_write(mnt);
|
||||
|
||||
getout:
|
||||
kfree(value);
|
||||
--- a/fs/xattr.c
|
||||
+++ b/fs/xattr.c
|
||||
@@ -190,7 +190,7 @@ vfs_listxattr(struct dentry *dentry, str
|
||||
EXPORT_SYMBOL_GPL(vfs_listxattr);
|
||||
|
||||
int
|
||||
-vfs_removexattr(struct dentry *dentry, const char *name)
|
||||
+vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, const char *name)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
int error;
|
||||
@@ -475,7 +475,7 @@ sys_flistxattr(int fd, char __user *list
|
||||
* Extended attribute REMOVE operations
|
||||
*/
|
||||
static long
|
||||
-removexattr(struct dentry *d, const char __user *name)
|
||||
+removexattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name)
|
||||
{
|
||||
int error;
|
||||
char kname[XATTR_NAME_MAX + 1];
|
||||
@@ -486,7 +486,7 @@ removexattr(struct dentry *d, const char
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
- return vfs_removexattr(d, kname);
|
||||
+ return vfs_removexattr(dentry, mnt, kname);
|
||||
}
|
||||
|
||||
asmlinkage long
|
||||
@@ -500,7 +500,7 @@ sys_removexattr(const char __user *pathn
|
||||
return error;
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (!error) {
|
||||
- error = removexattr(path.dentry, name);
|
||||
+ error = removexattr(path.dentry, path.mnt, name);
|
||||
mnt_drop_write(path.mnt);
|
||||
}
|
||||
path_put(&path);
|
||||
@@ -518,7 +518,7 @@ sys_lremovexattr(const char __user *path
|
||||
return error;
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (!error) {
|
||||
- error = removexattr(path.dentry, name);
|
||||
+ error = removexattr(path.dentry, path.mnt, name);
|
||||
mnt_drop_write(path.mnt);
|
||||
}
|
||||
path_put(&path);
|
||||
@@ -539,7 +539,7 @@ sys_fremovexattr(int fd, const char __us
|
||||
audit_inode(NULL, dentry);
|
||||
error = mnt_want_write(f->f_path.mnt);
|
||||
if (!error) {
|
||||
- error = removexattr(dentry, name);
|
||||
+ error = removexattr(dentry, f->f_path.mnt, name);
|
||||
mnt_drop_write(f->f_path.mnt);
|
||||
}
|
||||
fput(f);
|
||||
--- a/include/linux/xattr.h
|
||||
+++ b/include/linux/xattr.h
|
||||
@@ -51,7 +51,7 @@ ssize_t xattr_getsecurity(struct inode *
|
||||
ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, const char *, void *, size_t);
|
||||
ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list, size_t size);
|
||||
int vfs_setxattr(struct dentry *, struct vfsmount *, const char *, const void *, size_t, int);
|
||||
-int vfs_removexattr(struct dentry *, const char *);
|
||||
+int vfs_removexattr(struct dentry *, struct vfsmount *mnt, const char *);
|
||||
|
||||
ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
|
||||
ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
|
125
kernel-patches/2.6.28/vfs-rename.diff
Normal file
125
kernel-patches/2.6.28/vfs-rename.diff
Normal file
|
@ -0,0 +1,125 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Add struct vfsmount parameters to vfs_rename()
|
||||
|
||||
The vfsmount will be passed down to the LSM hook so that LSMs can compute
|
||||
pathnames.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/ecryptfs/inode.c | 7 ++++++-
|
||||
fs/namei.c | 19 ++++++++++++-------
|
||||
fs/nfsd/vfs.c | 3 ++-
|
||||
include/linux/fs.h | 2 +-
|
||||
4 files changed, 21 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/fs/ecryptfs/inode.c
|
||||
+++ b/fs/ecryptfs/inode.c
|
||||
@@ -590,19 +590,24 @@ ecryptfs_rename(struct inode *old_dir, s
|
||||
{
|
||||
int rc;
|
||||
struct dentry *lower_old_dentry;
|
||||
+ struct vfsmount *lower_old_mnt;
|
||||
struct dentry *lower_new_dentry;
|
||||
+ struct vfsmount *lower_new_mnt;
|
||||
struct dentry *lower_old_dir_dentry;
|
||||
struct dentry *lower_new_dir_dentry;
|
||||
|
||||
lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
|
||||
+ lower_old_mnt = ecryptfs_dentry_to_lower_mnt(old_dentry);
|
||||
lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
|
||||
+ lower_new_mnt = ecryptfs_dentry_to_lower_mnt(new_dentry);
|
||||
dget(lower_old_dentry);
|
||||
dget(lower_new_dentry);
|
||||
lower_old_dir_dentry = dget_parent(lower_old_dentry);
|
||||
lower_new_dir_dentry = dget_parent(lower_new_dentry);
|
||||
lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
|
||||
rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
|
||||
- lower_new_dir_dentry->d_inode, lower_new_dentry);
|
||||
+ lower_old_mnt, lower_new_dir_dentry->d_inode,
|
||||
+ lower_new_dentry, lower_new_mnt);
|
||||
if (rc)
|
||||
goto out_lock;
|
||||
fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL);
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -2502,7 +2502,8 @@ asmlinkage long sys_link(const char __us
|
||||
* locking].
|
||||
*/
|
||||
static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
|
||||
- struct inode *new_dir, struct dentry *new_dentry)
|
||||
+ struct vfsmount *old_mnt, struct inode *new_dir,
|
||||
+ struct dentry *new_dentry, struct vfsmount *new_mnt)
|
||||
{
|
||||
int error = 0;
|
||||
struct inode *target;
|
||||
@@ -2545,7 +2546,8 @@ static int vfs_rename_dir(struct inode *
|
||||
}
|
||||
|
||||
static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
|
||||
- struct inode *new_dir, struct dentry *new_dentry)
|
||||
+ struct vfsmount *old_mnt, struct inode *new_dir,
|
||||
+ struct dentry *new_dentry, struct vfsmount *new_mnt)
|
||||
{
|
||||
struct inode *target;
|
||||
int error;
|
||||
@@ -2573,7 +2575,8 @@ static int vfs_rename_other(struct inode
|
||||
}
|
||||
|
||||
int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
- struct inode *new_dir, struct dentry *new_dentry)
|
||||
+ struct vfsmount *old_mnt, struct inode *new_dir,
|
||||
+ struct dentry *new_dentry, struct vfsmount *new_mnt)
|
||||
{
|
||||
int error;
|
||||
int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
|
||||
@@ -2602,9 +2605,11 @@ int vfs_rename(struct inode *old_dir, st
|
||||
old_name = fsnotify_oldname_init(old_dentry->d_name.name);
|
||||
|
||||
if (is_dir)
|
||||
- error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
|
||||
+ error = vfs_rename_dir(old_dir, old_dentry, old_mnt,
|
||||
+ new_dir, new_dentry, new_mnt);
|
||||
else
|
||||
- error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
|
||||
+ error = vfs_rename_other(old_dir, old_dentry, old_mnt,
|
||||
+ new_dir, new_dentry, new_mnt);
|
||||
if (!error) {
|
||||
const char *new_name = old_dentry->d_name.name;
|
||||
fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir,
|
||||
@@ -2685,8 +2690,8 @@ asmlinkage long sys_renameat(int olddfd,
|
||||
error = mnt_want_write(oldnd.path.mnt);
|
||||
if (error)
|
||||
goto exit5;
|
||||
- error = vfs_rename(old_dir->d_inode, old_dentry,
|
||||
- new_dir->d_inode, new_dentry);
|
||||
+ error = vfs_rename(old_dir->d_inode, old_dentry, oldnd.path.mnt,
|
||||
+ new_dir->d_inode, new_dentry, newnd.path.mnt);
|
||||
mnt_drop_write(oldnd.path.mnt);
|
||||
exit5:
|
||||
dput(new_dentry);
|
||||
--- a/fs/nfsd/vfs.c
|
||||
+++ b/fs/nfsd/vfs.c
|
||||
@@ -1727,7 +1727,8 @@ nfsd_rename(struct svc_rqst *rqstp, stru
|
||||
if (host_err)
|
||||
goto out_dput_new;
|
||||
|
||||
- host_err = vfs_rename(fdir, odentry, tdir, ndentry);
|
||||
+ host_err = vfs_rename(fdir, odentry, ffhp->fh_export->ex_path.mnt,
|
||||
+ tdir, ndentry, tfhp->fh_export->ex_path.mnt);
|
||||
if (!host_err && EX_ISSYNC(tfhp->fh_export)) {
|
||||
host_err = nfsd_sync_dir(tdentry);
|
||||
if (!host_err)
|
||||
--- a/include/linux/fs.h
|
||||
+++ b/include/linux/fs.h
|
||||
@@ -1211,7 +1211,7 @@ extern int vfs_symlink(struct inode *, s
|
||||
extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
|
||||
extern int vfs_rmdir(struct inode *, struct dentry *, struct vfsmount *);
|
||||
extern int vfs_unlink(struct inode *, struct dentry *, struct vfsmount *);
|
||||
-extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
|
||||
+extern int vfs_rename(struct inode *, struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
|
||||
|
||||
/*
|
||||
* VFS dentry helper functions.
|
135
kernel-patches/2.6.28/vfs-rmdir.diff
Normal file
135
kernel-patches/2.6.28/vfs-rmdir.diff
Normal file
|
@ -0,0 +1,135 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Add a struct vfsmount parameter to vfs_rmdir()
|
||||
|
||||
The vfsmount will be passed down to the LSM hook so that LSMs can compute
|
||||
pathnames.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/ecryptfs/inode.c | 4 +++-
|
||||
fs/namei.c | 4 ++--
|
||||
fs/nfsd/nfs4recover.c | 2 +-
|
||||
fs/nfsd/vfs.c | 8 +++++---
|
||||
fs/reiserfs/xattr.c | 2 +-
|
||||
include/linux/fs.h | 2 +-
|
||||
6 files changed, 13 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/fs/ecryptfs/inode.c
|
||||
+++ b/fs/ecryptfs/inode.c
|
||||
@@ -534,14 +534,16 @@ out:
|
||||
static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
{
|
||||
struct dentry *lower_dentry;
|
||||
+ struct vfsmount *lower_mnt;
|
||||
struct dentry *lower_dir_dentry;
|
||||
int rc;
|
||||
|
||||
lower_dentry = ecryptfs_dentry_to_lower(dentry);
|
||||
+ lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
|
||||
dget(dentry);
|
||||
lower_dir_dentry = lock_parent(lower_dentry);
|
||||
dget(lower_dentry);
|
||||
- rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
|
||||
+ rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry, lower_mnt);
|
||||
dput(lower_dentry);
|
||||
if (!rc)
|
||||
d_delete(lower_dentry);
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -2115,7 +2115,7 @@ void dentry_unhash(struct dentry *dentry
|
||||
spin_unlock(&dcache_lock);
|
||||
}
|
||||
|
||||
-int vfs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
+int vfs_rmdir(struct inode *dir, struct dentry *dentry,struct vfsmount *mnt)
|
||||
{
|
||||
int error = may_delete(dir, dentry, 1);
|
||||
|
||||
@@ -2181,7 +2181,7 @@ static long do_rmdir(int dfd, const char
|
||||
error = mnt_want_write(nd.path.mnt);
|
||||
if (error)
|
||||
goto exit3;
|
||||
- error = vfs_rmdir(nd.path.dentry->d_inode, dentry);
|
||||
+ error = vfs_rmdir(nd.path.dentry->d_inode, dentry, nd.path.mnt);
|
||||
mnt_drop_write(nd.path.mnt);
|
||||
exit3:
|
||||
dput(dentry);
|
||||
--- a/fs/nfsd/nfs4recover.c
|
||||
+++ b/fs/nfsd/nfs4recover.c
|
||||
@@ -279,7 +279,7 @@ nfsd4_clear_clid_dir(struct dentry *dir,
|
||||
* a kernel from the future.... */
|
||||
nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file);
|
||||
mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
|
||||
- status = vfs_rmdir(dir->d_inode, dentry);
|
||||
+ status = vfs_rmdir(dir->d_inode, dentry, rec_dir.path.mnt);
|
||||
mutex_unlock(&dir->d_inode->i_mutex);
|
||||
return status;
|
||||
}
|
||||
--- a/fs/nfsd/vfs.c
|
||||
+++ b/fs/nfsd/vfs.c
|
||||
@@ -1765,6 +1765,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
|
||||
char *fname, int flen)
|
||||
{
|
||||
struct dentry *dentry, *rdentry;
|
||||
+ struct svc_export *exp;
|
||||
struct inode *dirp;
|
||||
__be32 err;
|
||||
int host_err;
|
||||
@@ -1779,6 +1780,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
|
||||
fh_lock_nested(fhp, I_MUTEX_PARENT);
|
||||
dentry = fhp->fh_dentry;
|
||||
dirp = dentry->d_inode;
|
||||
+ exp = fhp->fh_export;
|
||||
|
||||
rdentry = lookup_one_len(fname, dentry, flen);
|
||||
host_err = PTR_ERR(rdentry);
|
||||
@@ -1800,21 +1802,21 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
|
||||
|
||||
if (type != S_IFDIR) { /* It's UNLINK */
|
||||
#ifdef MSNFS
|
||||
- if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
|
||||
+ if ((exp->ex_flags & NFSEXP_MSNFS) &&
|
||||
(atomic_read(&rdentry->d_count) > 1)) {
|
||||
host_err = -EPERM;
|
||||
} else
|
||||
#endif
|
||||
host_err = vfs_unlink(dirp, rdentry);
|
||||
} else { /* It's RMDIR */
|
||||
- host_err = vfs_rmdir(dirp, rdentry);
|
||||
+ host_err = vfs_rmdir(dirp, rdentry, exp->ex_path.mnt);
|
||||
}
|
||||
|
||||
dput(rdentry);
|
||||
|
||||
if (host_err)
|
||||
goto out_drop;
|
||||
- if (EX_ISSYNC(fhp->fh_export))
|
||||
+ if (EX_ISSYNC(exp))
|
||||
host_err = nfsd_sync_dir(dentry);
|
||||
|
||||
out_drop:
|
||||
--- a/fs/reiserfs/xattr.c
|
||||
+++ b/fs/reiserfs/xattr.c
|
||||
@@ -746,7 +746,7 @@ int reiserfs_delete_xattrs(struct inode
|
||||
if (dir->d_inode->i_nlink <= 2) {
|
||||
root = get_xa_root(inode->i_sb, XATTR_REPLACE);
|
||||
reiserfs_write_lock_xattrs(inode->i_sb);
|
||||
- err = vfs_rmdir(root->d_inode, dir);
|
||||
+ err = vfs_rmdir(root->d_inode, dir, NULL);
|
||||
reiserfs_write_unlock_xattrs(inode->i_sb);
|
||||
dput(root);
|
||||
} else {
|
||||
--- a/include/linux/fs.h
|
||||
+++ b/include/linux/fs.h
|
||||
@@ -1209,7 +1209,7 @@ extern int vfs_mkdir(struct inode *, str
|
||||
extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t);
|
||||
extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *);
|
||||
extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
|
||||
-extern int vfs_rmdir(struct inode *, struct dentry *);
|
||||
+extern int vfs_rmdir(struct inode *, struct dentry *, struct vfsmount *);
|
||||
extern int vfs_unlink(struct inode *, struct dentry *);
|
||||
extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
|
||||
|
159
kernel-patches/2.6.28/vfs-setxattr.diff
Normal file
159
kernel-patches/2.6.28/vfs-setxattr.diff
Normal file
|
@ -0,0 +1,159 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Add a struct vfsmount parameter to vfs_setxattr()
|
||||
|
||||
The vfsmount will be passed down to the LSM hook so that LSMs can compute
|
||||
pathnames.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/nfsd/vfs.c | 16 +++++++++++-----
|
||||
fs/xattr.c | 16 ++++++++--------
|
||||
include/linux/xattr.h | 3 ++-
|
||||
3 files changed, 21 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/fs/nfsd/vfs.c
|
||||
+++ b/fs/nfsd/vfs.c
|
||||
@@ -429,7 +429,8 @@ static ssize_t nfsd_getxattr(struct dent
|
||||
|
||||
#if defined(CONFIG_NFSD_V4)
|
||||
static int
|
||||
-set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
|
||||
+set_nfsv4_acl_one(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ struct posix_acl *pacl, char *key)
|
||||
{
|
||||
int len;
|
||||
size_t buflen;
|
||||
@@ -448,7 +449,7 @@ set_nfsv4_acl_one(struct dentry *dentry,
|
||||
goto out;
|
||||
}
|
||||
|
||||
- error = vfs_setxattr(dentry, key, buf, len, 0);
|
||||
+ error = vfs_setxattr(dentry, mnt, key, buf, len, 0);
|
||||
out:
|
||||
kfree(buf);
|
||||
return error;
|
||||
@@ -461,6 +462,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
|
||||
__be32 error;
|
||||
int host_error;
|
||||
struct dentry *dentry;
|
||||
+ struct vfsmount *mnt;
|
||||
struct inode *inode;
|
||||
struct posix_acl *pacl = NULL, *dpacl = NULL;
|
||||
unsigned int flags = 0;
|
||||
@@ -471,6 +473,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
|
||||
return error;
|
||||
|
||||
dentry = fhp->fh_dentry;
|
||||
+ mnt = fhp->fh_export->ex_path.mnt;
|
||||
inode = dentry->d_inode;
|
||||
if (S_ISDIR(inode->i_mode))
|
||||
flags = NFS4_ACL_DIR;
|
||||
@@ -481,12 +484,14 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
|
||||
} else if (host_error < 0)
|
||||
goto out_nfserr;
|
||||
|
||||
- host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
|
||||
+ host_error = set_nfsv4_acl_one(dentry, mnt, pacl,
|
||||
+ POSIX_ACL_XATTR_ACCESS);
|
||||
if (host_error < 0)
|
||||
goto out_release;
|
||||
|
||||
if (S_ISDIR(inode->i_mode))
|
||||
- host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
|
||||
+ host_error = set_nfsv4_acl_one(dentry, mnt, dpacl,
|
||||
+ POSIX_ACL_XATTR_DEFAULT);
|
||||
|
||||
out_release:
|
||||
posix_acl_release(pacl);
|
||||
@@ -2202,7 +2207,8 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
|
||||
if (error)
|
||||
goto getout;
|
||||
if (size)
|
||||
- error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
|
||||
+ error = vfs_setxattr(fhp->fh_dentry, fhp->fh_export->ex_path.mnt,
|
||||
+ name, value, size,0);
|
||||
else {
|
||||
if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
|
||||
error = 0;
|
||||
--- a/fs/xattr.c
|
||||
+++ b/fs/xattr.c
|
||||
@@ -67,8 +67,8 @@ xattr_permission(struct inode *inode, co
|
||||
}
|
||||
|
||||
int
|
||||
-vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
|
||||
- size_t size, int flags)
|
||||
+vfs_setxattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
|
||||
+ const void *value, size_t size, int flags)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
int error;
|
||||
@@ -218,8 +218,8 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
|
||||
* Extended attribute SET operations
|
||||
*/
|
||||
static long
|
||||
-setxattr(struct dentry *d, const char __user *name, const void __user *value,
|
||||
- size_t size, int flags)
|
||||
+setxattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name,
|
||||
+ const void __user *value, size_t size, int flags)
|
||||
{
|
||||
int error;
|
||||
void *kvalue = NULL;
|
||||
@@ -246,7 +246,7 @@ setxattr(struct dentry *d, const char __
|
||||
}
|
||||
}
|
||||
|
||||
- error = vfs_setxattr(d, kname, kvalue, size, flags);
|
||||
+ error = vfs_setxattr(dentry, mnt, kname, kvalue, size, flags);
|
||||
kfree(kvalue);
|
||||
return error;
|
||||
}
|
||||
@@ -263,7 +263,7 @@ sys_setxattr(const char __user *pathname
|
||||
return error;
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (!error) {
|
||||
- error = setxattr(path.dentry, name, value, size, flags);
|
||||
+ error = setxattr(path.dentry, path.mnt, name, value, size, flags);
|
||||
mnt_drop_write(path.mnt);
|
||||
}
|
||||
path_put(&path);
|
||||
@@ -282,7 +282,7 @@ sys_lsetxattr(const char __user *pathnam
|
||||
return error;
|
||||
error = mnt_want_write(path.mnt);
|
||||
if (!error) {
|
||||
- error = setxattr(path.dentry, name, value, size, flags);
|
||||
+ error = setxattr(path.dentry, path.mnt, name, value, size, flags);
|
||||
mnt_drop_write(path.mnt);
|
||||
}
|
||||
path_put(&path);
|
||||
@@ -304,7 +304,7 @@ sys_fsetxattr(int fd, const char __user
|
||||
audit_inode(NULL, dentry);
|
||||
error = mnt_want_write(f->f_path.mnt);
|
||||
if (!error) {
|
||||
- error = setxattr(dentry, name, value, size, flags);
|
||||
+ error = setxattr(dentry, f->f_vfsmnt, name, value, size, flags);
|
||||
mnt_drop_write(f->f_path.mnt);
|
||||
}
|
||||
fput(f);
|
||||
--- a/include/linux/xattr.h
|
||||
+++ b/include/linux/xattr.h
|
||||
@@ -16,6 +16,7 @@
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/types.h>
|
||||
+#include <linux/mount.h>
|
||||
|
||||
/* Namespaces */
|
||||
#define XATTR_OS2_PREFIX "os2."
|
||||
@@ -49,7 +50,7 @@ struct xattr_handler {
|
||||
ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
|
||||
ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
|
||||
ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
|
||||
-int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int);
|
||||
+int vfs_setxattr(struct dentry *, struct vfsmount *, const char *, const void *, size_t, int);
|
||||
int vfs_removexattr(struct dentry *, const char *);
|
||||
|
||||
ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
|
123
kernel-patches/2.6.28/vfs-symlink.diff
Normal file
123
kernel-patches/2.6.28/vfs-symlink.diff
Normal file
|
@ -0,0 +1,123 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Add a struct vfsmount parameter to vfs_symlink()
|
||||
|
||||
The vfsmount will be passed down to the LSM hook so that LSMs can compute
|
||||
pathnames.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/ecryptfs/inode.c | 4 +++-
|
||||
fs/namei.c | 5 +++--
|
||||
fs/nfsd/vfs.c | 12 ++++++++----
|
||||
include/linux/fs.h | 2 +-
|
||||
4 files changed, 15 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/fs/ecryptfs/inode.c
|
||||
+++ b/fs/ecryptfs/inode.c
|
||||
@@ -464,6 +464,7 @@ static int ecryptfs_symlink(struct inode
|
||||
{
|
||||
int rc;
|
||||
struct dentry *lower_dentry;
|
||||
+ struct vfsmount *lower_mnt;
|
||||
struct dentry *lower_dir_dentry;
|
||||
char *encoded_symname;
|
||||
int encoded_symlen;
|
||||
@@ -471,6 +472,7 @@ static int ecryptfs_symlink(struct inode
|
||||
|
||||
lower_dentry = ecryptfs_dentry_to_lower(dentry);
|
||||
dget(lower_dentry);
|
||||
+ lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
|
||||
lower_dir_dentry = lock_parent(lower_dentry);
|
||||
encoded_symlen = ecryptfs_encode_filename(crypt_stat, symname,
|
||||
strlen(symname),
|
||||
@@ -479,7 +481,7 @@ static int ecryptfs_symlink(struct inode
|
||||
rc = encoded_symlen;
|
||||
goto out_lock;
|
||||
}
|
||||
- rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry,
|
||||
+ rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry, lower_mnt,
|
||||
encoded_symname);
|
||||
kfree(encoded_symname);
|
||||
if (rc || !lower_dentry->d_inode)
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -2301,7 +2301,8 @@ asmlinkage long sys_unlink(const char __
|
||||
return do_unlinkat(AT_FDCWD, pathname);
|
||||
}
|
||||
|
||||
-int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
|
||||
+int vfs_symlink(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *oldname)
|
||||
{
|
||||
int error = may_create(dir, dentry);
|
||||
|
||||
@@ -2347,7 +2348,7 @@ asmlinkage long sys_symlinkat(const char
|
||||
error = mnt_want_write(nd.path.mnt);
|
||||
if (error)
|
||||
goto out_dput;
|
||||
- error = vfs_symlink(nd.path.dentry->d_inode, dentry, from);
|
||||
+ error = vfs_symlink(nd.path.dentry->d_inode, dentry, nd.path.mnt, from);
|
||||
mnt_drop_write(nd.path.mnt);
|
||||
out_dput:
|
||||
dput(dentry);
|
||||
--- a/fs/nfsd/vfs.c
|
||||
+++ b/fs/nfsd/vfs.c
|
||||
@@ -1520,6 +1520,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
|
||||
struct iattr *iap)
|
||||
{
|
||||
struct dentry *dentry, *dnew;
|
||||
+ struct svc_export *exp;
|
||||
__be32 err, cerr;
|
||||
int host_err;
|
||||
|
||||
@@ -1544,6 +1545,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
|
||||
if (host_err)
|
||||
goto out_nfserr;
|
||||
|
||||
+ exp = fhp->fh_export;
|
||||
if (unlikely(path[plen] != 0)) {
|
||||
char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
|
||||
if (path_alloced == NULL)
|
||||
@@ -1551,14 +1553,16 @@ nfsd_symlink(struct svc_rqst *rqstp, str
|
||||
else {
|
||||
strncpy(path_alloced, path, plen);
|
||||
path_alloced[plen] = 0;
|
||||
- host_err = vfs_symlink(dentry->d_inode, dnew, path_alloced);
|
||||
+ host_err = vfs_symlink(dentry->d_inode, dnew,
|
||||
+ exp->ex_path.mnt, path_alloced);
|
||||
kfree(path_alloced);
|
||||
}
|
||||
} else
|
||||
- host_err = vfs_symlink(dentry->d_inode, dnew, path);
|
||||
+ host_err = vfs_symlink(dentry->d_inode, dnew, exp->ex_path.mnt,
|
||||
+ path);
|
||||
|
||||
if (!host_err) {
|
||||
- if (EX_ISSYNC(fhp->fh_export))
|
||||
+ if (EX_ISSYNC(exp))
|
||||
host_err = nfsd_sync_dir(dentry);
|
||||
}
|
||||
err = nfserrno(host_err);
|
||||
@@ -1566,7 +1570,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
|
||||
|
||||
mnt_drop_write(fhp->fh_export->ex_path.mnt);
|
||||
|
||||
- cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
|
||||
+ cerr = fh_compose(resfhp, exp, dnew, fhp);
|
||||
dput(dnew);
|
||||
if (err==0) err = cerr;
|
||||
out:
|
||||
--- a/include/linux/fs.h
|
||||
+++ b/include/linux/fs.h
|
||||
@@ -1207,7 +1207,7 @@ extern int vfs_permission(struct nameida
|
||||
extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *);
|
||||
extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int);
|
||||
extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t);
|
||||
-extern int vfs_symlink(struct inode *, struct dentry *, const char *);
|
||||
+extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *);
|
||||
extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
|
||||
extern int vfs_rmdir(struct inode *, struct dentry *);
|
||||
extern int vfs_unlink(struct inode *, struct dentry *);
|
99
kernel-patches/2.6.28/vfs-unlink.diff
Normal file
99
kernel-patches/2.6.28/vfs-unlink.diff
Normal file
|
@ -0,0 +1,99 @@
|
|||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Add a struct vfsmount parameter to vfs_unlink()
|
||||
|
||||
The vfsmount will be passed down to the LSM hook so that LSMs can compute
|
||||
pathnames.
|
||||
|
||||
Signed-off-by: Tony Jones <tonyj@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
fs/ecryptfs/inode.c | 3 ++-
|
||||
fs/namei.c | 4 ++--
|
||||
fs/nfsd/nfs4recover.c | 2 +-
|
||||
fs/nfsd/vfs.c | 2 +-
|
||||
include/linux/fs.h | 2 +-
|
||||
ipc/mqueue.c | 2 +-
|
||||
6 files changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/fs/ecryptfs/inode.c
|
||||
+++ b/fs/ecryptfs/inode.c
|
||||
@@ -445,11 +445,12 @@ static int ecryptfs_unlink(struct inode
|
||||
{
|
||||
int rc = 0;
|
||||
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
|
||||
+ struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
|
||||
struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir);
|
||||
struct dentry *lower_dir_dentry;
|
||||
|
||||
lower_dir_dentry = lock_parent(lower_dentry);
|
||||
- rc = vfs_unlink(lower_dir_inode, lower_dentry);
|
||||
+ rc = vfs_unlink(lower_dir_inode, lower_dentry, lower_mnt);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc);
|
||||
goto out_unlock;
|
||||
--- a/fs/namei.c
|
||||
+++ b/fs/namei.c
|
||||
@@ -2199,7 +2199,7 @@ asmlinkage long sys_rmdir(const char __u
|
||||
return do_rmdir(AT_FDCWD, pathname);
|
||||
}
|
||||
|
||||
-int vfs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
+int vfs_unlink(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt)
|
||||
{
|
||||
int error = may_delete(dir, dentry, 0);
|
||||
|
||||
@@ -2267,7 +2267,7 @@ static long do_unlinkat(int dfd, const c
|
||||
error = mnt_want_write(nd.path.mnt);
|
||||
if (error)
|
||||
goto exit2;
|
||||
- error = vfs_unlink(nd.path.dentry->d_inode, dentry);
|
||||
+ error = vfs_unlink(nd.path.dentry->d_inode, dentry, nd.path.mnt);
|
||||
mnt_drop_write(nd.path.mnt);
|
||||
exit2:
|
||||
dput(dentry);
|
||||
--- a/fs/nfsd/nfs4recover.c
|
||||
+++ b/fs/nfsd/nfs4recover.c
|
||||
@@ -264,7 +264,7 @@ nfsd4_remove_clid_file(struct dentry *di
|
||||
return -EINVAL;
|
||||
}
|
||||
mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
|
||||
- status = vfs_unlink(dir->d_inode, dentry);
|
||||
+ status = vfs_unlink(dir->d_inode, dentry, rec_dir.path.mnt);
|
||||
mutex_unlock(&dir->d_inode->i_mutex);
|
||||
return status;
|
||||
}
|
||||
--- a/fs/nfsd/vfs.c
|
||||
+++ b/fs/nfsd/vfs.c
|
||||
@@ -1807,7 +1807,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
|
||||
host_err = -EPERM;
|
||||
} else
|
||||
#endif
|
||||
- host_err = vfs_unlink(dirp, rdentry);
|
||||
+ host_err = vfs_unlink(dirp, rdentry, exp->ex_path.mnt);
|
||||
} else { /* It's RMDIR */
|
||||
host_err = vfs_rmdir(dirp, rdentry, exp->ex_path.mnt);
|
||||
}
|
||||
--- a/include/linux/fs.h
|
||||
+++ b/include/linux/fs.h
|
||||
@@ -1210,7 +1210,7 @@ extern int vfs_mknod(struct inode *, str
|
||||
extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *);
|
||||
extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
|
||||
extern int vfs_rmdir(struct inode *, struct dentry *, struct vfsmount *);
|
||||
-extern int vfs_unlink(struct inode *, struct dentry *);
|
||||
+extern int vfs_unlink(struct inode *, struct dentry *, struct vfsmount *);
|
||||
extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
|
||||
|
||||
/*
|
||||
--- a/ipc/mqueue.c
|
||||
+++ b/ipc/mqueue.c
|
||||
@@ -753,7 +753,7 @@ asmlinkage long sys_mq_unlink(const char
|
||||
err = mnt_want_write(mqueue_mnt);
|
||||
if (err)
|
||||
goto out_err;
|
||||
- err = vfs_unlink(dentry->d_parent->d_inode, dentry);
|
||||
+ err = vfs_unlink(dentry->d_parent->d_inode, dentry, mqueue_mnt);
|
||||
mnt_drop_write(mqueue_mnt);
|
||||
out_err:
|
||||
dput(dentry);
|
Loading…
Add table
Reference in a new issue