diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /fs/ecryptfs/messaging.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'fs/ecryptfs/messaging.c')
-rw-r--r-- | fs/ecryptfs/messaging.c | 135 |
1 files changed, 120 insertions, 15 deletions
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c index 5fa2471796c..ab224809051 100644 --- a/fs/ecryptfs/messaging.c +++ b/fs/ecryptfs/messaging.c | |||
@@ -32,8 +32,8 @@ static struct mutex ecryptfs_msg_ctx_lists_mux; | |||
32 | static struct hlist_head *ecryptfs_daemon_hash; | 32 | static struct hlist_head *ecryptfs_daemon_hash; |
33 | struct mutex ecryptfs_daemon_hash_mux; | 33 | struct mutex ecryptfs_daemon_hash_mux; |
34 | static int ecryptfs_hash_bits; | 34 | static int ecryptfs_hash_bits; |
35 | #define ecryptfs_current_euid_hash(uid) \ | 35 | #define ecryptfs_uid_hash(uid) \ |
36 | hash_long((unsigned long)from_kuid(&init_user_ns, current_euid()), ecryptfs_hash_bits) | 36 | hash_long((unsigned long)uid, ecryptfs_hash_bits) |
37 | 37 | ||
38 | static u32 ecryptfs_msg_counter; | 38 | static u32 ecryptfs_msg_counter; |
39 | static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; | 39 | static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; |
@@ -105,23 +105,26 @@ void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx) | |||
105 | 105 | ||
106 | /** | 106 | /** |
107 | * ecryptfs_find_daemon_by_euid | 107 | * ecryptfs_find_daemon_by_euid |
108 | * @euid: The effective user id which maps to the desired daemon id | ||
109 | * @user_ns: The namespace in which @euid applies | ||
108 | * @daemon: If return value is zero, points to the desired daemon pointer | 110 | * @daemon: If return value is zero, points to the desired daemon pointer |
109 | * | 111 | * |
110 | * Must be called with ecryptfs_daemon_hash_mux held. | 112 | * Must be called with ecryptfs_daemon_hash_mux held. |
111 | * | 113 | * |
112 | * Search the hash list for the current effective user id. | 114 | * Search the hash list for the given user id. |
113 | * | 115 | * |
114 | * Returns zero if the user id exists in the list; non-zero otherwise. | 116 | * Returns zero if the user id exists in the list; non-zero otherwise. |
115 | */ | 117 | */ |
116 | int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon) | 118 | int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon, uid_t euid, |
119 | struct user_namespace *user_ns) | ||
117 | { | 120 | { |
118 | struct hlist_node *elem; | 121 | struct hlist_node *elem; |
119 | int rc; | 122 | int rc; |
120 | 123 | ||
121 | hlist_for_each_entry(*daemon, elem, | 124 | hlist_for_each_entry(*daemon, elem, |
122 | &ecryptfs_daemon_hash[ecryptfs_current_euid_hash()], | 125 | &ecryptfs_daemon_hash[ecryptfs_uid_hash(euid)], |
123 | euid_chain) { | 126 | euid_chain) { |
124 | if (uid_eq((*daemon)->file->f_cred->euid, current_euid())) { | 127 | if ((*daemon)->euid == euid && (*daemon)->user_ns == user_ns) { |
125 | rc = 0; | 128 | rc = 0; |
126 | goto out; | 129 | goto out; |
127 | } | 130 | } |
@@ -134,7 +137,9 @@ out: | |||
134 | /** | 137 | /** |
135 | * ecryptfs_spawn_daemon - Create and initialize a new daemon struct | 138 | * ecryptfs_spawn_daemon - Create and initialize a new daemon struct |
136 | * @daemon: Pointer to set to newly allocated daemon struct | 139 | * @daemon: Pointer to set to newly allocated daemon struct |
137 | * @file: File used when opening /dev/ecryptfs | 140 | * @euid: Effective user id for the daemon |
141 | * @user_ns: The namespace in which @euid applies | ||
142 | * @pid: Process id for the daemon | ||
138 | * | 143 | * |
139 | * Must be called ceremoniously while in possession of | 144 | * Must be called ceremoniously while in possession of |
140 | * ecryptfs_sacred_daemon_hash_mux | 145 | * ecryptfs_sacred_daemon_hash_mux |
@@ -142,7 +147,8 @@ out: | |||
142 | * Returns zero on success; non-zero otherwise | 147 | * Returns zero on success; non-zero otherwise |
143 | */ | 148 | */ |
144 | int | 149 | int |
145 | ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, struct file *file) | 150 | ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, |
151 | struct user_namespace *user_ns, struct pid *pid) | ||
146 | { | 152 | { |
147 | int rc = 0; | 153 | int rc = 0; |
148 | 154 | ||
@@ -153,13 +159,16 @@ ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, struct file *file) | |||
153 | "GFP_KERNEL memory\n", __func__, sizeof(**daemon)); | 159 | "GFP_KERNEL memory\n", __func__, sizeof(**daemon)); |
154 | goto out; | 160 | goto out; |
155 | } | 161 | } |
156 | (*daemon)->file = file; | 162 | (*daemon)->euid = euid; |
163 | (*daemon)->user_ns = get_user_ns(user_ns); | ||
164 | (*daemon)->pid = get_pid(pid); | ||
165 | (*daemon)->task = current; | ||
157 | mutex_init(&(*daemon)->mux); | 166 | mutex_init(&(*daemon)->mux); |
158 | INIT_LIST_HEAD(&(*daemon)->msg_ctx_out_queue); | 167 | INIT_LIST_HEAD(&(*daemon)->msg_ctx_out_queue); |
159 | init_waitqueue_head(&(*daemon)->wait); | 168 | init_waitqueue_head(&(*daemon)->wait); |
160 | (*daemon)->num_queued_msg_ctx = 0; | 169 | (*daemon)->num_queued_msg_ctx = 0; |
161 | hlist_add_head(&(*daemon)->euid_chain, | 170 | hlist_add_head(&(*daemon)->euid_chain, |
162 | &ecryptfs_daemon_hash[ecryptfs_current_euid_hash()]); | 171 | &ecryptfs_daemon_hash[ecryptfs_uid_hash(euid)]); |
163 | out: | 172 | out: |
164 | return rc; | 173 | return rc; |
165 | } | 174 | } |
@@ -179,6 +188,9 @@ int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon) | |||
179 | if ((daemon->flags & ECRYPTFS_DAEMON_IN_READ) | 188 | if ((daemon->flags & ECRYPTFS_DAEMON_IN_READ) |
180 | || (daemon->flags & ECRYPTFS_DAEMON_IN_POLL)) { | 189 | || (daemon->flags & ECRYPTFS_DAEMON_IN_POLL)) { |
181 | rc = -EBUSY; | 190 | rc = -EBUSY; |
191 | printk(KERN_WARNING "%s: Attempt to destroy daemon with pid " | ||
192 | "[0x%p], but it is in the midst of a read or a poll\n", | ||
193 | __func__, daemon->pid); | ||
182 | mutex_unlock(&daemon->mux); | 194 | mutex_unlock(&daemon->mux); |
183 | goto out; | 195 | goto out; |
184 | } | 196 | } |
@@ -191,6 +203,12 @@ int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon) | |||
191 | ecryptfs_msg_ctx_alloc_to_free(msg_ctx); | 203 | ecryptfs_msg_ctx_alloc_to_free(msg_ctx); |
192 | } | 204 | } |
193 | hlist_del(&daemon->euid_chain); | 205 | hlist_del(&daemon->euid_chain); |
206 | if (daemon->task) | ||
207 | wake_up_process(daemon->task); | ||
208 | if (daemon->pid) | ||
209 | put_pid(daemon->pid); | ||
210 | if (daemon->user_ns) | ||
211 | put_user_ns(daemon->user_ns); | ||
194 | mutex_unlock(&daemon->mux); | 212 | mutex_unlock(&daemon->mux); |
195 | kzfree(daemon); | 213 | kzfree(daemon); |
196 | out: | 214 | out: |
@@ -198,9 +216,42 @@ out: | |||
198 | } | 216 | } |
199 | 217 | ||
200 | /** | 218 | /** |
219 | * ecryptfs_process_quit | ||
220 | * @euid: The user ID owner of the message | ||
221 | * @user_ns: The namespace in which @euid applies | ||
222 | * @pid: The process ID for the userspace program that sent the | ||
223 | * message | ||
224 | * | ||
225 | * Deletes the corresponding daemon for the given euid and pid, if | ||
226 | * it is the registered that is requesting the deletion. Returns zero | ||
227 | * after deleting the desired daemon; non-zero otherwise. | ||
228 | */ | ||
229 | int ecryptfs_process_quit(uid_t euid, struct user_namespace *user_ns, | ||
230 | struct pid *pid) | ||
231 | { | ||
232 | struct ecryptfs_daemon *daemon; | ||
233 | int rc; | ||
234 | |||
235 | mutex_lock(&ecryptfs_daemon_hash_mux); | ||
236 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, user_ns); | ||
237 | if (rc || !daemon) { | ||
238 | rc = -EINVAL; | ||
239 | printk(KERN_ERR "Received request from user [%d] to " | ||
240 | "unregister unrecognized daemon [0x%p]\n", euid, pid); | ||
241 | goto out_unlock; | ||
242 | } | ||
243 | rc = ecryptfs_exorcise_daemon(daemon); | ||
244 | out_unlock: | ||
245 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
246 | return rc; | ||
247 | } | ||
248 | |||
249 | /** | ||
201 | * ecryptfs_process_reponse | 250 | * ecryptfs_process_reponse |
202 | * @msg: The ecryptfs message received; the caller should sanity check | 251 | * @msg: The ecryptfs message received; the caller should sanity check |
203 | * msg->data_len and free the memory | 252 | * msg->data_len and free the memory |
253 | * @pid: The process ID of the userspace application that sent the | ||
254 | * message | ||
204 | * @seq: The sequence number of the message; must match the sequence | 255 | * @seq: The sequence number of the message; must match the sequence |
205 | * number for the existing message context waiting for this | 256 | * number for the existing message context waiting for this |
206 | * response | 257 | * response |
@@ -219,11 +270,16 @@ out: | |||
219 | * | 270 | * |
220 | * Returns zero on success; non-zero otherwise | 271 | * Returns zero on success; non-zero otherwise |
221 | */ | 272 | */ |
222 | int ecryptfs_process_response(struct ecryptfs_daemon *daemon, | 273 | int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, |
223 | struct ecryptfs_message *msg, u32 seq) | 274 | struct user_namespace *user_ns, struct pid *pid, |
275 | u32 seq) | ||
224 | { | 276 | { |
277 | struct ecryptfs_daemon *uninitialized_var(daemon); | ||
225 | struct ecryptfs_msg_ctx *msg_ctx; | 278 | struct ecryptfs_msg_ctx *msg_ctx; |
226 | size_t msg_size; | 279 | size_t msg_size; |
280 | struct nsproxy *nsproxy; | ||
281 | struct user_namespace *tsk_user_ns; | ||
282 | uid_t ctx_euid; | ||
227 | int rc; | 283 | int rc; |
228 | 284 | ||
229 | if (msg->index >= ecryptfs_message_buf_len) { | 285 | if (msg->index >= ecryptfs_message_buf_len) { |
@@ -236,6 +292,51 @@ int ecryptfs_process_response(struct ecryptfs_daemon *daemon, | |||
236 | } | 292 | } |
237 | msg_ctx = &ecryptfs_msg_ctx_arr[msg->index]; | 293 | msg_ctx = &ecryptfs_msg_ctx_arr[msg->index]; |
238 | mutex_lock(&msg_ctx->mux); | 294 | mutex_lock(&msg_ctx->mux); |
295 | mutex_lock(&ecryptfs_daemon_hash_mux); | ||
296 | rcu_read_lock(); | ||
297 | nsproxy = task_nsproxy(msg_ctx->task); | ||
298 | if (nsproxy == NULL) { | ||
299 | rc = -EBADMSG; | ||
300 | printk(KERN_ERR "%s: Receiving process is a zombie. Dropping " | ||
301 | "message.\n", __func__); | ||
302 | rcu_read_unlock(); | ||
303 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
304 | goto wake_up; | ||
305 | } | ||
306 | tsk_user_ns = __task_cred(msg_ctx->task)->user->user_ns; | ||
307 | ctx_euid = task_euid(msg_ctx->task); | ||
308 | rc = ecryptfs_find_daemon_by_euid(&daemon, ctx_euid, tsk_user_ns); | ||
309 | rcu_read_unlock(); | ||
310 | mutex_unlock(&ecryptfs_daemon_hash_mux); | ||
311 | if (rc) { | ||
312 | rc = -EBADMSG; | ||
313 | printk(KERN_WARNING "%s: User [%d] received a " | ||
314 | "message response from process [0x%p] but does " | ||
315 | "not have a registered daemon\n", __func__, | ||
316 | ctx_euid, pid); | ||
317 | goto wake_up; | ||
318 | } | ||
319 | if (ctx_euid != euid) { | ||
320 | rc = -EBADMSG; | ||
321 | printk(KERN_WARNING "%s: Received message from user " | ||
322 | "[%d]; expected message from user [%d]\n", __func__, | ||
323 | euid, ctx_euid); | ||
324 | goto unlock; | ||
325 | } | ||
326 | if (tsk_user_ns != user_ns) { | ||
327 | rc = -EBADMSG; | ||
328 | printk(KERN_WARNING "%s: Received message from user_ns " | ||
329 | "[0x%p]; expected message from user_ns [0x%p]\n", | ||
330 | __func__, user_ns, tsk_user_ns); | ||
331 | goto unlock; | ||
332 | } | ||
333 | if (daemon->pid != pid) { | ||
334 | rc = -EBADMSG; | ||
335 | printk(KERN_ERR "%s: User [%d] sent a message response " | ||
336 | "from an unrecognized process [0x%p]\n", | ||
337 | __func__, ctx_euid, pid); | ||
338 | goto unlock; | ||
339 | } | ||
239 | if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) { | 340 | if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) { |
240 | rc = -EINVAL; | 341 | rc = -EINVAL; |
241 | printk(KERN_WARNING "%s: Desired context element is not " | 342 | printk(KERN_WARNING "%s: Desired context element is not " |
@@ -258,8 +359,9 @@ int ecryptfs_process_response(struct ecryptfs_daemon *daemon, | |||
258 | } | 359 | } |
259 | memcpy(msg_ctx->msg, msg, msg_size); | 360 | memcpy(msg_ctx->msg, msg, msg_size); |
260 | msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE; | 361 | msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_DONE; |
261 | wake_up_process(msg_ctx->task); | ||
262 | rc = 0; | 362 | rc = 0; |
363 | wake_up: | ||
364 | wake_up_process(msg_ctx->task); | ||
263 | unlock: | 365 | unlock: |
264 | mutex_unlock(&msg_ctx->mux); | 366 | mutex_unlock(&msg_ctx->mux); |
265 | out: | 367 | out: |
@@ -281,11 +383,14 @@ ecryptfs_send_message_locked(char *data, int data_len, u8 msg_type, | |||
281 | struct ecryptfs_msg_ctx **msg_ctx) | 383 | struct ecryptfs_msg_ctx **msg_ctx) |
282 | { | 384 | { |
283 | struct ecryptfs_daemon *daemon; | 385 | struct ecryptfs_daemon *daemon; |
386 | uid_t euid = current_euid(); | ||
284 | int rc; | 387 | int rc; |
285 | 388 | ||
286 | rc = ecryptfs_find_daemon_by_euid(&daemon); | 389 | rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); |
287 | if (rc || !daemon) { | 390 | if (rc || !daemon) { |
288 | rc = -ENOTCONN; | 391 | rc = -ENOTCONN; |
392 | printk(KERN_ERR "%s: User [%d] does not have a daemon " | ||
393 | "registered\n", __func__, euid); | ||
289 | goto out; | 394 | goto out; |
290 | } | 395 | } |
291 | mutex_lock(&ecryptfs_msg_ctx_lists_mux); | 396 | mutex_lock(&ecryptfs_msg_ctx_lists_mux); |