aboutsummaryrefslogtreecommitdiffstats
path: root/security/apparmor/procattr.c
diff options
context:
space:
mode:
authorJohn Johansen <john.johansen@canonical.com>2010-07-29 17:48:03 -0400
committerJames Morris <jmorris@namei.org>2010-08-02 01:35:13 -0400
commit63e2b423771ab0bc7ad4d407f3f6517c6d05cdc0 (patch)
treee50efc9593c7558d3700ec55869f9ddbac283a1d /security/apparmor/procattr.c
parente06f75a6a2b43bd3a7a197bd21466f9da130e4af (diff)
AppArmor: userspace interfaces
The /proc/<pid>/attr/* interface is used for process introspection and commands. While the apparmorfs interface is used for global introspection and loading and removing policy. The interface currently only contains the files necessary for loading policy, and will be extended in the future to include sysfs style single per file introspection inteface. The old AppArmor 2.4 interface files have been removed into a compatibility patch, that distros can use to maintain backwards compatibility. Signed-off-by: John Johansen <john.johansen@canonical.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/apparmor/procattr.c')
-rw-r--r--security/apparmor/procattr.c170
1 files changed, 170 insertions, 0 deletions
diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c
new file mode 100644
index 000000000000..04a2cf8d1b65
--- /dev/null
+++ b/security/apparmor/procattr.c
@@ -0,0 +1,170 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor /proc/<pid>/attr/ interface functions
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#include "include/apparmor.h"
16#include "include/context.h"
17#include "include/policy.h"
18#include "include/domain.h"
19
20
21/**
22 * aa_getprocattr - Return the profile information for @profile
23 * @profile: the profile to print profile info about (NOT NULL)
24 * @string: Returns - string containing the profile info (NOT NULL)
25 *
26 * Returns: length of @string on success else error on failure
27 *
28 * Requires: profile != NULL
29 *
30 * Creates a string containing the namespace_name://profile_name for
31 * @profile.
32 *
33 * Returns: size of string placed in @string else error code on failure
34 */
35int aa_getprocattr(struct aa_profile *profile, char **string)
36{
37 char *str;
38 int len = 0, mode_len = 0, ns_len = 0, name_len;
39 const char *mode_str = profile_mode_names[profile->mode];
40 const char *ns_name = NULL;
41 struct aa_namespace *ns = profile->ns;
42 struct aa_namespace *current_ns = __aa_current_profile()->ns;
43 char *s;
44
45 if (!aa_ns_visible(current_ns, ns))
46 return -EACCES;
47
48 ns_name = aa_ns_name(current_ns, ns);
49 ns_len = strlen(ns_name);
50
51 /* if the visible ns_name is > 0 increase size for : :// seperator */
52 if (ns_len)
53 ns_len += 4;
54
55 /* unconfined profiles don't have a mode string appended */
56 if (!unconfined(profile))
57 mode_len = strlen(mode_str) + 3; /* + 3 for _() */
58
59 name_len = strlen(profile->base.hname);
60 len = mode_len + ns_len + name_len + 1; /* + 1 for \n */
61 s = str = kmalloc(len + 1, GFP_KERNEL); /* + 1 \0 */
62 if (!str)
63 return -ENOMEM;
64
65 if (ns_len) {
66 /* skip over prefix current_ns->base.hname and separating // */
67 sprintf(s, ":%s://", ns_name);
68 s += ns_len;
69 }
70 if (unconfined(profile))
71 /* mode string not being appended */
72 sprintf(s, "%s\n", profile->base.hname);
73 else
74 sprintf(s, "%s (%s)\n", profile->base.hname, mode_str);
75 *string = str;
76
77 /* NOTE: len does not include \0 of string, not saved as part of file */
78 return len;
79}
80
81/**
82 * split_token_from_name - separate a string of form <token>^<name>
83 * @op: operation being checked
84 * @args: string to parse (NOT NULL)
85 * @token: stores returned parsed token value (NOT NULL)
86 *
87 * Returns: start position of name after token else NULL on failure
88 */
89static char *split_token_from_name(int op, char *args, u64 * token)
90{
91 char *name;
92
93 *token = simple_strtoull(args, &name, 16);
94 if ((name == args) || *name != '^') {
95 AA_ERROR("%s: Invalid input '%s'", op_table[op], args);
96 return ERR_PTR(-EINVAL);
97 }
98
99 name++; /* skip ^ */
100 if (!*name)
101 name = NULL;
102 return name;
103}
104
105/**
106 * aa_setprocattr_chagnehat - handle procattr interface to change_hat
107 * @args: args received from writing to /proc/<pid>/attr/current (NOT NULL)
108 * @size: size of the args
109 * @test: true if this is a test of change_hat permissions
110 *
111 * Returns: %0 or error code if change_hat fails
112 */
113int aa_setprocattr_changehat(char *args, size_t size, int test)
114{
115 char *hat;
116 u64 token;
117 const char *hats[16]; /* current hard limit on # of names */
118 int count = 0;
119
120 hat = split_token_from_name(OP_CHANGE_HAT, args, &token);
121 if (IS_ERR(hat))
122 return PTR_ERR(hat);
123
124 if (!hat && !token) {
125 AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
126 return -EINVAL;
127 }
128
129 if (hat) {
130 /* set up hat name vector, args guaranteed null terminated
131 * at args[size] by setprocattr.
132 *
133 * If there are multiple hat names in the buffer each is
134 * separated by a \0. Ie. userspace writes them pre tokenized
135 */
136 char *end = args + size;
137 for (count = 0; (hat < end) && count < 16; ++count) {
138 char *next = hat + strlen(hat) + 1;
139 hats[count] = hat;
140 hat = next;
141 }
142 }
143
144 AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
145 __func__, token, hat ? hat : NULL);
146
147 return aa_change_hat(hats, count, token, test);
148}
149
150/**
151 * aa_setprocattr_changeprofile - handle procattr interface to changeprofile
152 * @fqname: args received from writting to /proc/<pid>/attr/current (NOT NULL)
153 * @onexec: true if change_profile should be delayed until exec
154 * @test: true if this is a test of change_profile permissions
155 *
156 * Returns: %0 or error code if change_profile fails
157 */
158int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test)
159{
160 char *name, *ns_name;
161
162 name = aa_split_fqname(fqname, &ns_name);
163 return aa_change_profile(ns_name, name, onexec, test);
164}
165
166int aa_setprocattr_permipc(char *fqname)
167{
168 /* TODO: add ipc permission querying */
169 return -ENOTSUPP;
170}