1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
From: Cyrill Gorcunov <gorcunov@openvz.org>
Date: Wed, 8 Dec 2010 14:10:42 +0000 (+0300)
Subject: cpt: Use init_task credentials for file restoring procedure
X-Git-Url: http://git.openvz.org/?p=linux-2.6.32-openvz;a=commitdiff_plain;h=66d247cf6dd51c6725cef2d01285398fe667ef6f
cpt: Use init_task credentials for file restoring procedure
We need highest credentials for file restoring procedure otherwise
we might hit the situation where credentials for restoring thread
is not high enough (happens with programs changing their uids).
http://bugzilla.openvz.org/show_bug.cgi?id=1603
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
---
diff --git a/kernel/cpt/rst_files.c b/kernel/cpt/rst_files.c
index a84e3d3..75d591e 100644
--- a/kernel/cpt/rst_files.c
+++ b/kernel/cpt/rst_files.c
@@ -616,12 +616,11 @@ out:
return err;
}
-static int fixup_file_flags(struct file *file, struct cpt_file_image *fi,
+static int fixup_file_flags(struct file *file, const struct cred *cred,
+ struct cpt_file_image *fi,
int was_dentry_open, loff_t pos,
cpt_context_t *ctx)
{
- const struct cred *cred = current_cred() /* should be valid already */;
-
if (fi->cpt_pos != file->f_pos) {
int err = -ESPIPE;
if (file->f_op->llseek)
@@ -824,6 +823,34 @@ static struct file *open_signalfd(struct cpt_file_image *fi, int flags, struct c
}
#endif
+/*
+ * It may happen that a process which created a file
+ * had changed its UID after that (keeping file opened/referenced
+ * with write permissions for 'own' only) as a result we might
+ * be unable to read it at restore time due to credentials
+ * mismatch, to break this tie we temporary take 'init_task' credentials
+ * and as only the file gets read into the memory we restore original
+ * credentials back
+ *
+ * Same time if between credentials rise/restore you need
+ * the former credentials (for fixups or whatever) --
+ * use rst_cred_origin for that
+ */
+static const struct cred *rst_cred_origin;
+
+void rst_creds_rise_current(void)
+{
+ struct task_struct *tsk = &init_task;
+ BUG_ON(rst_cred_origin);
+ rst_cred_origin = override_creds(tsk->cred);
+}
+
+void rst_creds_restore_current(void)
+{
+ revert_creds(rst_cred_origin);
+ rst_cred_origin = NULL;
+}
+
struct file *rst_file(loff_t pos, int fd, struct cpt_context *ctx)
{
int err;
@@ -836,6 +863,8 @@ struct file *rst_file(loff_t pos, int fd, struct cpt_context *ctx)
struct proc_dir_entry *proc_dead_file;
int flags;
+ rst_creds_rise_current();
+
obj = lookup_cpt_obj_bypos(CPT_OBJ_FILE, pos, ctx);
if (obj) {
file = obj->o_obj;
@@ -844,9 +873,10 @@ struct file *rst_file(loff_t pos, int fd, struct cpt_context *ctx)
err = rst_get_object(CPT_OBJ_FILE, pos, &fi, ctx);
if (err < 0)
goto err_out;
- fixup_file_flags(file, &fi, 0, pos, ctx);
+ fixup_file_flags(file, rst_cred, &fi, 0, pos, ctx);
}
get_file(file);
+ rst_creds_restore_current();
return file;
}
@@ -1006,7 +1036,7 @@ open_file:
}
map_file:
if (!IS_ERR(file)) {
- fixup_file_flags(file, &fi, was_dentry_open, pos, ctx);
+ fixup_file_flags(file, rst_cred, &fi, was_dentry_open, pos, ctx);
if (S_ISFIFO(fi.cpt_i_mode) && !was_dentry_open) {
err = fixup_pipe_data(file, &fi, ctx);
@@ -1059,6 +1089,7 @@ map_file:
out:
if (name)
rst_put_name(name, ctx);
+ rst_creds_restore_current();
return file;
err_put:
@@ -1067,6 +1098,7 @@ err_put:
err_out:
if (name)
rst_put_name(name, ctx);
+ rst_creds_restore_current();
return ERR_PTR(err);
}
|