diff options
-rw-r--r-- | Documentation/sysctl/kernel.txt | 25 | ||||
-rw-r--r-- | lib/vsprintf.c | 33 |
2 files changed, 48 insertions, 10 deletions
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 4273b2d71a27..26b7ee491df8 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt | |||
@@ -290,13 +290,24 @@ Default value is "/sbin/hotplug". | |||
290 | kptr_restrict: | 290 | kptr_restrict: |
291 | 291 | ||
292 | This toggle indicates whether restrictions are placed on | 292 | This toggle indicates whether restrictions are placed on |
293 | exposing kernel addresses via /proc and other interfaces. When | 293 | exposing kernel addresses via /proc and other interfaces. |
294 | kptr_restrict is set to (0), there are no restrictions. When | 294 | |
295 | kptr_restrict is set to (1), the default, kernel pointers | 295 | When kptr_restrict is set to (0), the default, there are no restrictions. |
296 | printed using the %pK format specifier will be replaced with 0's | 296 | |
297 | unless the user has CAP_SYSLOG. When kptr_restrict is set to | 297 | When kptr_restrict is set to (1), kernel pointers printed using the %pK |
298 | (2), kernel pointers printed using %pK will be replaced with 0's | 298 | format specifier will be replaced with 0's unless the user has CAP_SYSLOG |
299 | regardless of privileges. | 299 | and effective user and group ids are equal to the real ids. This is |
300 | because %pK checks are done at read() time rather than open() time, so | ||
301 | if permissions are elevated between the open() and the read() (e.g via | ||
302 | a setuid binary) then %pK will not leak kernel pointers to unprivileged | ||
303 | users. Note, this is a temporary solution only. The correct long-term | ||
304 | solution is to do the permission checks at open() time. Consider removing | ||
305 | world read permissions from files that use %pK, and using dmesg_restrict | ||
306 | to protect against uses of %pK in dmesg(8) if leaking kernel pointer | ||
307 | values to unprivileged users is a concern. | ||
308 | |||
309 | When kptr_restrict is set to (2), kernel pointers printed using | ||
310 | %pK will be replaced with 0's regardless of privileges. | ||
300 | 311 | ||
301 | ============================================================== | 312 | ============================================================== |
302 | 313 | ||
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 26559bdb4c49..d76555c45ff4 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/uaccess.h> | 27 | #include <linux/uaccess.h> |
28 | #include <linux/ioport.h> | 28 | #include <linux/ioport.h> |
29 | #include <linux/dcache.h> | 29 | #include <linux/dcache.h> |
30 | #include <linux/cred.h> | ||
30 | #include <net/addrconf.h> | 31 | #include <net/addrconf.h> |
31 | 32 | ||
32 | #include <asm/page.h> /* for PAGE_SIZE */ | 33 | #include <asm/page.h> /* for PAGE_SIZE */ |
@@ -1312,11 +1313,37 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
1312 | spec.field_width = default_width; | 1313 | spec.field_width = default_width; |
1313 | return string(buf, end, "pK-error", spec); | 1314 | return string(buf, end, "pK-error", spec); |
1314 | } | 1315 | } |
1315 | if (!((kptr_restrict == 0) || | 1316 | |
1316 | (kptr_restrict == 1 && | 1317 | switch (kptr_restrict) { |
1317 | has_capability_noaudit(current, CAP_SYSLOG)))) | 1318 | case 0: |
1319 | /* Always print %pK values */ | ||
1320 | break; | ||
1321 | case 1: { | ||
1322 | /* | ||
1323 | * Only print the real pointer value if the current | ||
1324 | * process has CAP_SYSLOG and is running with the | ||
1325 | * same credentials it started with. This is because | ||
1326 | * access to files is checked at open() time, but %pK | ||
1327 | * checks permission at read() time. We don't want to | ||
1328 | * leak pointer values if a binary opens a file using | ||
1329 | * %pK and then elevates privileges before reading it. | ||
1330 | */ | ||
1331 | const struct cred *cred = current_cred(); | ||
1332 | |||
1333 | if (!has_capability_noaudit(current, CAP_SYSLOG) || | ||
1334 | !uid_eq(cred->euid, cred->uid) || | ||
1335 | !gid_eq(cred->egid, cred->gid)) | ||
1336 | ptr = NULL; | ||
1337 | break; | ||
1338 | } | ||
1339 | case 2: | ||
1340 | default: | ||
1341 | /* Always print 0's for %pK */ | ||
1318 | ptr = NULL; | 1342 | ptr = NULL; |
1343 | break; | ||
1344 | } | ||
1319 | break; | 1345 | break; |
1346 | |||
1320 | case 'N': | 1347 | case 'N': |
1321 | switch (fmt[1]) { | 1348 | switch (fmt[1]) { |
1322 | case 'F': | 1349 | case 'F': |