~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to debian/patches/features/all/fs-symlink-restrictions-on-sticky-directories.patch

  • Committer: Package Import Robot
  • Author(s): Ben Hutchings, Bastian Blank, Ben Hutchings, Uwe Kleine-König
  • Date: 2012-03-04 15:32:20 UTC
  • mfrom: (43.1.29 sid)
  • Revision ID: package-import@ubuntu.com-20120304153220-r171jd27k3dd3639
Tags: 3.2.9-1
* New upstream stable update:
  http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.8
  - [i386] i387: move TS_USEDFPU flag from thread_info to task_struct
  - [x86] additional refactoring of FPU/SSE state save and restore
  http://www.kernel.org/pub/linux/kernel/v3.x/ChangeLog-3.2.9
  - vfs: fix d_inode_lookup() dentry ref leak
  - target: Allow control CDBs with data > 1 page
  - epoll: introduce POLLFREE to flush ->signalfd_wqh before kfree()
  - epoll: ep_unregister_pollwait() can use the freed pwq->whead
  - epoll: limit paths (CVE-2011-1083)
  - cdrom: use copy_to_user() without the underscores

[ Bastian Blank ]
* [mips,mipsel] Also remove ext4 modules from installer.

[ Ben Hutchings ]
* Update debconf template translations:
  - Update Dutch (Willem Kuyn) (Closes: #658736)
  - Add Polish (Michał Kułach) (Closes: #658912)
* Bump ABI to 2
* fs: Introduce and enable security restrictions on links:
  - Do not follow symlinks in /tmp that are owned by other users
    (sysctl: fs.protected_symlinks)
  - Do not allow unprivileged users to create hard links to sensitive files
    (sysctl: fs.protected_hardlinks) (Closes: #609455)
    + This breaks the 'at' package in stable, which will be fixed shortly
      (see #597130)
  The precise restrictions are specified in Documentation/sysctl/fs.txt in
  the linux-doc-3.2 and linux-source-3.2 packages.
* iwlwifi: fix key removal (Closes: #651199)
* cgroups: Set CGROUP_PERF
* hid: Enable HID_HOLTEK, HID_PRIMAX, HID_SPEEDLINK, HID_WIIMOTE as modules,
  HID_ACRUX_FF
* media/rc: Enable RC_ATI_REMOTE as module
* gspca: Enable USB_GSPCA_TOPRO as module
* dvb-usb: Enable DVB_USB_PCTV452E, DVB_USB_MXL111SF as modules

[ Uwe Kleine-König ]
* [x86] Update rt featureset to 3.2.9-rt15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
From af16d0017a7de1f00af3966b5013bebfce8a81b4 Mon Sep 17 00:00:00 2001
 
2
From: Kees Cook <keescook@chromium.org>
 
3
Date: Sat, 25 Feb 2012 12:28:42 +1100
 
4
Subject: [PATCH 1/5] fs: symlink restrictions on sticky directories
 
5
MIME-Version: 1.0
 
6
Content-Type: text/plain; charset=UTF-8
 
7
Content-Transfer-Encoding: 8bit
 
8
 
 
9
A longstanding class of security issues is the symlink-based
 
10
time-of-check-time-of-use race, most commonly seen in world-writable
 
11
directories like /tmp.  The common method of exploitation of this flaw is
 
12
to cross privilege boundaries when following a given symlink (i.e.  a root
 
13
process follows a symlink belonging to another user).  For a likely
 
14
incomplete list of hundreds of examples across the years, please see:
 
15
http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=/tmp
 
16
 
 
17
The solution is to permit symlinks to only be followed when outside a
 
18
sticky world-writable directory, or when the uid of the symlink and
 
19
follower match, or when the directory owner matches the symlink's owner.
 
20
 
 
21
Some pointers to the history of earlier discussion that I could find:
 
22
 
 
23
 1996 Aug, Zygo Blaxell
 
24
  http://marc.info/?l=bugtraq&m=87602167419830&w=2
 
25
 1996 Oct, Andrew Tridgell
 
26
  http://lkml.indiana.edu/hypermail/linux/kernel/9610.2/0086.html
 
27
 1997 Dec, Albert D Cahalan
 
28
  http://lkml.org/lkml/1997/12/16/4
 
29
 2005 Feb, Lorenzo Hernández García-Hierro
 
30
  http://lkml.indiana.edu/hypermail/linux/kernel/0502.0/1896.html
 
31
 2010 May, Kees Cook
 
32
  https://lkml.org/lkml/2010/5/30/144
 
33
 
 
34
Past objections and rebuttals could be summarized as:
 
35
 
 
36
 - Violates POSIX.
 
37
   - POSIX didn't consider this situation and it's not useful to follow
 
38
     a broken specification at the cost of security.
 
39
 - Might break unknown applications that use this feature.
 
40
   - Applications that break because of the change are easy to spot and
 
41
     fix. Applications that are vulnerable to symlink ToCToU by not having
 
42
     the change aren't. Additionally, no applications have yet been found
 
43
     that rely on this behavior.
 
44
 - Applications should just use mkstemp() or O_CREATE|O_EXCL.
 
45
   - True, but applications are not perfect, and new software is written
 
46
     all the time that makes these mistakes; blocking this flaw at the
 
47
     kernel is a single solution to the entire class of vulnerability.
 
48
 - This should live in the core VFS.
 
49
   - This should live in an LSM. (https://lkml.org/lkml/2010/5/31/135)
 
50
 - This should live in an LSM.
 
51
   - This should live in the core VFS. (https://lkml.org/lkml/2010/8/2/188)
 
52
 
 
53
This patch is based on the patch in Openwall and grsecurity, along with
 
54
suggestions from Al Viro.  I have added a sysctl to enable the protected
 
55
behavior, documentation, and an audit notification.
 
56
 
 
57
[akpm@linux-foundation.org: move sysctl_protected_sticky_symlinks declaration into .h]
 
58
Signed-off-by: Kees Cook <keescook@chromium.org>
 
59
Reviewed-by: Ingo Molnar <mingo@elte.hu>
 
60
Cc: Matthew Wilcox <matthew@wil.cx>
 
61
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
 
62
Cc: Rik van Riel <riel@redhat.com>
 
63
Cc: Federica Teodori <federica.teodori@googlemail.com>
 
64
Cc: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>
 
65
Cc: Ingo Molnar <mingo@elte.hu>
 
66
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
 
67
Cc: Eric Paris <eparis@redhat.com>
 
68
Cc: Randy Dunlap <rdunlap@xenotime.net>
 
69
Cc: Dan Rosenberg <drosenberg@vsecurity.com>
 
70
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
 
71
---
 
72
 Documentation/sysctl/fs.txt |   21 ++++++++++
 
73
 fs/Kconfig                  |   34 ++++++++++++++++
 
74
 fs/namei.c                  |   91 ++++++++++++++++++++++++++++++++++++++++---
 
75
 include/linux/fs.h          |    1 +
 
76
 kernel/sysctl.c             |   11 +++++
 
77
 5 files changed, 152 insertions(+), 6 deletions(-)
 
78
 
 
79
diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt
 
80
index 88fd7f5..4b47cd5 100644
 
81
--- a/Documentation/sysctl/fs.txt
 
82
+++ b/Documentation/sysctl/fs.txt
 
83
@@ -32,6 +32,7 @@ Currently, these files are in /proc/sys/fs:
 
84
 - nr_open
 
85
 - overflowuid
 
86
 - overflowgid
 
87
+- protected_sticky_symlinks
 
88
 - suid_dumpable
 
89
 - super-max
 
90
 - super-nr
 
91
@@ -157,6 +158,26 @@ The default is 65534.
 
92
 
 
93
 ==============================================================
 
94
 
 
95
+protected_sticky_symlinks:
 
96
+
 
97
+A long-standing class of security issues is the symlink-based
 
98
+time-of-check-time-of-use race, most commonly seen in world-writable
 
99
+directories like /tmp. The common method of exploitation of this flaw
 
100
+is to cross privilege boundaries when following a given symlink (i.e. a
 
101
+root process follows a symlink belonging to another user). For a likely
 
102
+incomplete list of hundreds of examples across the years, please see:
 
103
+http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=/tmp
 
104
+
 
105
+When set to "0", symlink following behavior is unrestricted.
 
106
+
 
107
+When set to "1" symlinks are permitted to be followed only when outside
 
108
+a sticky world-writable directory, or when the uid of the symlink and
 
109
+follower match, or when the directory owner matches the symlink's owner.
 
110
+
 
111
+This protection is based on the restrictions in Openwall and grsecurity.
 
112
+
 
113
+==============================================================
 
114
+
 
115
 suid_dumpable:
 
116
 
 
117
 This value can be used to query and set the core dump mode for setuid
 
118
diff --git a/fs/Kconfig b/fs/Kconfig
 
119
index 1497ddf..d0fdbdd 100644
 
120
--- a/fs/Kconfig
 
121
+++ b/fs/Kconfig
 
122
@@ -272,4 +272,38 @@ endif # NETWORK_FILESYSTEMS
 
123
 source "fs/nls/Kconfig"
 
124
 source "fs/dlm/Kconfig"
 
125
 
 
126
+config PROTECTED_STICKY_SYMLINKS
 
127
+       bool "Evaluate vulnerable symlink conditions"
 
128
+       default y
 
129
+       help
 
130
+         A long-standing class of security issues is the symlink-based
 
131
+         time-of-check-time-of-use race, most commonly seen in
 
132
+         world-writable directories like /tmp. The common method of
 
133
+         exploitation of this flaw is to cross privilege boundaries
 
134
+         when following a given symlink (i.e. a root process follows
 
135
+         a malicious symlink belonging to another user).
 
136
+
 
137
+         Enabling this adds the logic to examine these dangerous symlink
 
138
+         conditions. Whether or not the dangerous symlink situations are
 
139
+         allowed is controlled by PROTECTED_STICKY_SYMLINKS_ENABLED.
 
140
+
 
141
+config PROTECTED_STICKY_SYMLINKS_ENABLED
 
142
+       depends on PROTECTED_STICKY_SYMLINKS
 
143
+       bool "Disallow symlink following in sticky world-writable dirs"
 
144
+       default y
 
145
+       help
 
146
+         Solve ToCToU symlink race vulnerablities by permitting symlinks
 
147
+         to be followed only when outside a sticky world-writable directory,
 
148
+         or when the uid of the symlink and follower match, or when the
 
149
+         directory and symlink owners match.
 
150
+
 
151
+         When PROC_SYSCTL is enabled, this setting can also be controlled
 
152
+         via /proc/sys/kernel/protected_sticky_symlinks.
 
153
+
 
154
+config PROTECTED_STICKY_SYMLINKS_ENABLED_SYSCTL
 
155
+       depends on PROTECTED_STICKY_SYMLINKS
 
156
+       int
 
157
+       default "1" if PROTECTED_STICKY_SYMLINKS_ENABLED
 
158
+       default "0"
 
159
+
 
160
 endmenu
 
161
diff --git a/fs/namei.c b/fs/namei.c
 
162
index 5d1fab5..5b4c05b 100644
 
163
--- a/fs/namei.c
 
164
+++ b/fs/namei.c
 
165
@@ -623,10 +623,84 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki
 
166
        path_put(link);
 
167
 }
 
168
 
 
169
+#ifdef CONFIG_PROTECTED_STICKY_SYMLINKS
 
170
+int sysctl_protected_sticky_symlinks __read_mostly =
 
171
+       CONFIG_PROTECTED_STICKY_SYMLINKS_ENABLED_SYSCTL;
 
172
+
 
173
+/**
 
174
+ * may_follow_link - Check symlink following for unsafe situations
 
175
+ * @dentry: The inode/dentry of the symlink
 
176
+ * @nameidata: The path data of the symlink
 
177
+ *
 
178
+ * In the case of the protected_sticky_symlinks sysctl being enabled,
 
179
+ * CAP_DAC_OVERRIDE needs to be specifically ignored if the symlink is
 
180
+ * in a sticky world-writable directory. This is to protect privileged
 
181
+ * processes from failing races against path names that may change out
 
182
+ * from under them by way of other users creating malicious symlinks.
 
183
+ * It will permit symlinks to be followed only when outside a sticky
 
184
+ * world-writable directory, or when the uid of the symlink and follower
 
185
+ * match, or when the directory owner matches the symlink's owner.
 
186
+ *
 
187
+ * Returns 0 if following the symlink is allowed, -ve on error.
 
188
+ */
 
189
+static inline int
 
190
+may_follow_link(struct dentry *dentry, struct nameidata *nameidata)
 
191
+{
 
192
+       int error = 0;
 
193
+       const struct inode *parent;
 
194
+       const struct inode *inode;
 
195
+       const struct cred *cred;
 
196
+
 
197
+       if (!sysctl_protected_sticky_symlinks)
 
198
+               return 0;
 
199
+
 
200
+       /* Allowed if owner and follower match. */
 
201
+       cred = current_cred();
 
202
+       inode = dentry->d_inode;
 
203
+       if (cred->fsuid == inode->i_uid)
 
204
+               return 0;
 
205
+
 
206
+       /* Check parent directory mode and owner. */
 
207
+       spin_lock(&dentry->d_lock);
 
208
+       parent = dentry->d_parent->d_inode;
 
209
+       if ((parent->i_mode & (S_ISVTX|S_IWOTH)) == (S_ISVTX|S_IWOTH) &&
 
210
+           parent->i_uid != inode->i_uid) {
 
211
+               error = -EACCES;
 
212
+       }
 
213
+       spin_unlock(&dentry->d_lock);
 
214
+
 
215
+#ifdef CONFIG_AUDIT
 
216
+       if (error) {
 
217
+               struct audit_buffer *ab;
 
218
+
 
219
+               ab = audit_log_start(current->audit_context,
 
220
+                                    GFP_KERNEL, AUDIT_AVC);
 
221
+               audit_log_format(ab, "op=follow_link action=denied");
 
222
+               audit_log_format(ab, " pid=%d comm=", current->pid);
 
223
+               audit_log_untrustedstring(ab, current->comm);
 
224
+               audit_log_d_path(ab, " path=", &nameidata->path);
 
225
+               audit_log_format(ab, " name=");
 
226
+               audit_log_untrustedstring(ab, dentry->d_name.name);
 
227
+               audit_log_format(ab, " dev=");
 
228
+               audit_log_untrustedstring(ab, inode->i_sb->s_id);
 
229
+               audit_log_format(ab, " ino=%lu", inode->i_ino);
 
230
+               audit_log_end(ab);
 
231
+       }
 
232
+#endif
 
233
+       return error;
 
234
+}
 
235
+#else
 
236
+static inline int
 
237
+may_follow_link(struct dentry *dentry, struct nameidata *nameidata)
 
238
+{
 
239
+       return 0;
 
240
+}
 
241
+#endif
 
242
+
 
243
 static __always_inline int
 
244
-follow_link(struct path *link, struct nameidata *nd, void **p)
 
245
+follow_link(struct path *link, struct nameidata *nd, void **p, bool sensitive)
 
246
 {
 
247
-       int error;
 
248
+       int error = 0;
 
249
        struct dentry *dentry = link->dentry;
 
250
 
 
251
        BUG_ON(nd->flags & LOOKUP_RCU);
 
252
@@ -645,7 +719,10 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
 
253
        touch_atime(link->mnt, dentry);
 
254
        nd_set_link(nd, NULL);
 
255
 
 
256
-       error = security_inode_follow_link(link->dentry, nd);
 
257
+       if (sensitive)
 
258
+               error = may_follow_link(link->dentry, nd);
 
259
+       if (!error)
 
260
+               error = security_inode_follow_link(link->dentry, nd);
 
261
        if (error) {
 
262
                *p = ERR_PTR(error); /* no ->put_link(), please */
 
263
                path_put(&nd->path);
 
264
@@ -1342,7 +1419,7 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd)
 
265
                struct path link = *path;
 
266
                void *cookie;
 
267
 
 
268
-               res = follow_link(&link, nd, &cookie);
 
269
+               res = follow_link(&link, nd, &cookie, false);
 
270
                if (!res)
 
271
                        res = walk_component(nd, path, &nd->last,
 
272
                                             nd->last_type, LOOKUP_FOLLOW);
 
273
@@ -1615,7 +1692,8 @@ static int path_lookupat(int dfd, const char *name,
 
274
                        void *cookie;
 
275
                        struct path link = path;
 
276
                        nd->flags |= LOOKUP_PARENT;
 
277
-                       err = follow_link(&link, nd, &cookie);
 
278
+
 
279
+                       err = follow_link(&link, nd, &cookie, true);
 
280
                        if (!err)
 
281
                                err = lookup_last(nd, &path);
 
282
                        put_link(nd, &link, cookie);
 
283
@@ -2327,7 +2405,8 @@ static struct file *path_openat(int dfd, const char *pathname,
 
284
                }
 
285
                nd->flags |= LOOKUP_PARENT;
 
286
                nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
 
287
-               error = follow_link(&link, nd, &cookie);
 
288
+
 
289
+               error = follow_link(&link, nd, &cookie, true);
 
290
                if (unlikely(error))
 
291
                        filp = ERR_PTR(error);
 
292
                else
 
293
diff --git a/include/linux/fs.h b/include/linux/fs.h
 
294
index 9808b21..aba8db0 100644
 
295
--- a/include/linux/fs.h
 
296
+++ b/include/linux/fs.h
 
297
@@ -423,6 +423,7 @@ extern unsigned long get_max_files(void);
 
298
 extern int sysctl_nr_open;
 
299
 extern struct inodes_stat_t inodes_stat;
 
300
 extern int leases_enable, lease_break_time;
 
301
+extern int sysctl_protected_sticky_symlinks;
 
302
 
 
303
 struct buffer_head;
 
304
 typedef int (get_block_t)(struct inode *inode, sector_t iblock,
 
305
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
 
306
index 62538ee..c469b88 100644
 
307
--- a/kernel/sysctl.c
 
308
+++ b/kernel/sysctl.c
 
309
@@ -1497,6 +1497,17 @@ static struct ctl_table fs_table[] = {
 
310
        },
 
311
 #endif
 
312
 #endif
 
313
+#ifdef CONFIG_PROTECTED_STICKY_SYMLINKS
 
314
+       {
 
315
+               .procname       = "protected_sticky_symlinks",
 
316
+               .data           = &sysctl_protected_sticky_symlinks,
 
317
+               .maxlen         = sizeof(int),
 
318
+               .mode           = 0600,
 
319
+               .proc_handler   = proc_dointvec_minmax,
 
320
+               .extra1         = &zero,
 
321
+               .extra2         = &one,
 
322
+       },
 
323
+#endif
 
324
        {
 
325
                .procname       = "suid_dumpable",
 
326
                .data           = &suid_dumpable,
 
327
-- 
 
328
1.7.9.1
 
329