kernel/printk/printk.c: check_syslog_permissions() cleanup
PATCH 1/1 kernel/printk/printk.c: check_syslog_permissions() cleanup
Final version of patch 637241a900cb ("kmsg: honor dmesg_restrict sysctl on /dev/kmsg") lost few hooks. As result security_syslog() is not checked inside check_syslog_permissions() if dmesg_restrict is set, or it can be called twice in do_syslog().
--- kernel/printk/printk.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
kernel/printk/printk.c +4 -7
@@ -484,11 +484,11 @@ int check_syslog_permissions(int type, bool from_file)* already done the capabilities checks at open time. */ if (from_file && type !=SYSLOG_ACTION_OPEN ) -return 0 ; + goto ok;if (syslog_action_restricted (type)) {if (capable (CAP_SYSLOG )) -return 0 ; + goto ok;/* * For historical reasons, accept CAP_SYS_ADMIN too, with * a warning.
@@ -498,10 +498,11 @@ int check_syslog_permissions(int type, bool from_file)"CAP_SYS_ADMIN but no CAP_SYSLOG " "(deprecated).\n" , current->comm, task_pid_nr(current)); -return 0 ; + goto ok; }return -EPERM ; } +ok:return security_syslog (type); }
@@ -1263,10 +1264,6 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)if (error) goto out; - error =security_syslog (type); -if (error) -return error; -switch (type) {case SYSLOG_ACTION_CLOSE :/* Close log */ break ;
Signature · 1 line
1.9.1
Quoted 6 lines · On Sun, 10 May 2015 09:35:53 +0300 Vasily Averin <[email protected]> wrote:
Fixes 637241a900cb ("kmsg: honor dmesg_restrict sysctl on /dev/kmsg")Final version of patch
637241a900cb("kmsg: honordmesg_restrictsysctl on/dev/kmsg") lost few hooks. As resultsecurity_syslog()is not checked insidecheck_syslog_permissions()ifdmesg_restrictis set, or it can be called twice indo_syslog().
I'm not seeing how security_syslog() is called twice from do_syslog(). Put more details in the changelog, please.
kernel/printk/printk.c int check_syslog_permissions(int type, bool from_file) · line 487
Quoted 8 lines
kernel/printk/printk.c +1
-1@@ -484,11 +484,11 @@ int check_syslog_permissions(int type, bool from_file)* already done the capabilities checks at open time. */ if (from_file && type !=SYSLOG_ACTION_OPEN ) -return 0 ; + goto ok;
This seems wrong - we should only call security_syslog() for opens?
Quoted 10 lines
kernel/printk/printk.c +1
-1if (syslog_action_restricted (type)) {if (capable (CAP_SYSLOG )) -return 0 ; + goto ok;/* * For historical reasons, accept CAP_SYS_ADMIN too, with * a warning.
Quoted 11 lines · Andrew Morton
Quoted 6 lines · On Sun, 10 May 2015 09:35:53 +0300 Vasily Averin <[email protected]> wrote:
Fixes 637241a900cb ("kmsg: honor dmesg_restrict sysctl on /dev/kmsg")Final version of patch
637241a900cb("kmsg: honordmesg_restrictsysctl on/dev/kmsg") lost few hooks. As resultsecurity_syslog()is not checked insidecheck_syslog_permissions()ifdmesg_restrictis set, or it can be called twice indo_syslog().I'm not seeing how
security_syslog()is called twice fromdo_syslog(). Put more details in the changelog, please.
For example, if dmesg_restrict is not set and SYSLOG_ACTION_OPEN is requested. In this case do_syslog() calls check_syslog_permissions()
where security_syslog() is called first time and approves the operation, then do_syslog() itself calls security_syslog() 2nd time.
Quoted 10 lines
kernel/printk/printk.c int check_syslog_permissions(int type, bool from_file) · line 487
Quoted 8 lines
kernel/printk/printk.c +1
-1@@ -484,11 +484,11 @@ int check_syslog_permissions(int type, bool from_file)* already done the capabilities checks at open time. */ if (from_file && type !=SYSLOG_ACTION_OPEN ) -return 0 ; + goto ok;This seems wrong - we should only call
security_syslog()for opens?
Are you sure?
I saw Linus comment in thread related to old patch, and I agree that usual kernel checks can be skipped.
However I believe security hooks should be called anyway,
in general case they can have own rules about access, logging
or additional things that should be called before execution of requested operation.
Am I wrong?
Quoted 10 lines · Vasily Averin
Quoted 9 lines · Andrew Morton
Quoted 6 lines · On Sun, 10 May 2015 09:35:53 +0300 Vasily Averin <[email protected]> wrote:
Fixes 637241a900cb ("kmsg: honor dmesg_restrict sysctl on /dev/kmsg")Final version of patch
637241a900cb("kmsg: honordmesg_restrictsysctl on/dev/kmsg") lost few hooks. As resultsecurity_syslog()is not checked insidecheck_syslog_permissions()ifdmesg_restrictis set, or it can be called twice indo_syslog().
Quoted 4 lines
Quoted 2 lines
I'm not seeing how
security_syslog()is called twice fromdo_syslog(). Put more details in the changelog, please.For example, if
dmesg_restrictis not set andSYSLOG_ACTION_OPENis requested.
no, SYSLOG_ACTION_OPEN does not fit.
syslog_action_restricted() should return 0,
so it should be SYSLOG_ACTION_READ_ALL or SYSLOG_ACTION_SIZE_BUFFER commands and from_file should be set to SYSLOG_FROM_READER.
Quoted 4 lines
In this case
do_syslog()callscheck_syslog_permissions()wheresecurity_syslog()is called first time and approves the operation, thendo_syslog()itself callssecurity_syslog()2nd time.
Quoted 11 lines · Andrew Morton
kernel/printk/printk.c int check_syslog_permissions(int type, bool from_file) · line 487
Quoted 8 lines · On Sun, 10 May 2015 09:35:53 +0300 Vasily Averin <[email protected]> wrote:
kernel/printk/printk.c +1
-1@@ -484,11 +484,11 @@ int check_syslog_permissions(int type, bool from_file)* already done the capabilities checks at open time. */ if (from_file && type !=SYSLOG_ACTION_OPEN ) -return 0 ; + goto ok;This seems wrong - we should only call
security_syslog()for opens?
No I think my version is correct.
Currently security hook _is_ called in this situation:from_file is set in /proc/kmsg handlers only, they use do_syslog() and call security_syslog() directly after check_syslog_permissions() call.
My patch forces check_syslog_permissions() to call security hook in all cases, that allows to remove extra security_syslog() call from do_syslog().
I've changed patch comment and going to resend new patch version soon.
PATCH v2 1/1 security_syslog() should be called once only
In reply to Andrew Mortonv2: subject changed, patch comment modified
Final version of patch 637241a900cb ("kmsg: honor dmesg_restrict sysctl on /dev/kmsg") lost few hooks, as result security_syslog() are processed incorrectly:
- open of /dev/kmsg checks syslog access permissions by using check_syslog_permissions() where security_syslog() is not called if dmesg_restrict is set.
- syslog syscall and /proc/kmsg calls do_syslog()
where security_syslog can be executed twice
(inside check_syslog_permissions() and then directly in do_syslog())
With this patch security_syslog() is called once only in all syslog-related operations regardless of dmesg_restrict value.
--- kernel/printk/printk.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
kernel/printk/printk.c +4 -7
@@ -484,11 +484,11 @@ int check_syslog_permissions(int type, bool from_file)* already done the capabilities checks at open time. */ if (from_file && type !=SYSLOG_ACTION_OPEN ) -return 0 ; + goto ok;if (syslog_action_restricted (type)) {if (capable (CAP_SYSLOG )) -return 0 ; + goto ok;/* * For historical reasons, accept CAP_SYS_ADMIN too, with * a warning.
@@ -498,10 +498,11 @@ int check_syslog_permissions(int type, bool from_file)"CAP_SYS_ADMIN but no CAP_SYSLOG " "(deprecated).\n" , current->comm, task_pid_nr(current)); -return 0 ; + goto ok; }return -EPERM ; } +ok:return security_syslog (type); }
@@ -1263,10 +1264,6 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)if (error) goto out; - error =security_syslog (type); -if (error) -return error; -switch (type) {case SYSLOG_ACTION_CLOSE :/* Close log */ break ;
Signature · 1 line
1.9.1
Re: [PATCH v2] security_syslog() should be called once only
Quoted 22 lines · On Sun, 24 May 2015 19:18:40 +0300 Vasily Averin <[email protected]> wrote:
v2: subject changed, patch comment modified
Fixes 637241a900cb ("kmsg: honor dmesg_restrict sysctl on /dev/kmsg")Final version of patch
637241a900cb("kmsg: honordmesg_restrictsysctl on/dev/kmsg") lost few hooks, as resultsecurity_syslog()are processed incorrectly:
- open of/dev/kmsgchecks syslog access permissions by usingcheck_syslog_permissions()wheresecurity_syslog()is not called ifdmesg_restrictis set.
- syslog syscall and/proc/kmsgcallsdo_syslog()
wheresecurity_syslogcan be executed twice
(insidecheck_syslog_permissions()and then directly indo_syslog())With this patch
security_syslog()is called once only in all syslog-related operations regardless ofdmesg_restrictvalue....
kernel/printk/printk.c int check_syslog_permissions(int type, bool from_file) · line 487
Quoted 5 lines
kernel/printk/printk.c +1
-1@@ -484,11 +484,11 @@ int check_syslog_permissions(int type, bool from_file)* already done the capabilities checks at open time. */ if (from_file && type !=SYSLOG_ACTION_OPEN ) -return 0 ; + goto ok;
So we run security_syslog() for actions other than open() (of kmsg). Why?
Also, that from_file handling makes me cry.
#define SYSLOG_FROM_READER 0
#define SYSLOG_FROM_PROC 1
That's not a boolean - it's an enumerated value with two values currently defined.
But the code in check_syslog_permissions() treats it as a boolean and also hardwires the knowledge that SYSLOG_FROM_PROC == 1 (or == true).
And the name is wrong: it should be called from_proc to match SYSLOG_FROM_PROC.
One possible fix would be something like this, plus various fixups/audit:
kernel/printk/printk.c renamed from kernel/printk/printk.c~security_syslog-should-be-called-once-only-fix +2 -2
@@ -489,13 +489,13 @@ static int syslog_action_restricted(int type !=SYSLOG_ACTION_SIZE_BUFFER ; } -int check_syslog_permissions (int type,bool from_file) +int check_syslog_permissions (int type,int source) {/* * If this is from /proc/kmsg and we've already opened it, then we've * already done the capabilities checks at open time. */ -if (from_file && type !=SYSLOG_ACTION_OPEN ) +if (source ==SYSLOG_FROM_PROC && type !=SYSLOG_ACTION_OPEN ) goto ok;if (syslog_action_restricted (type)) {
_
And type' should be renamed to action' for heavens sake. Kees, were you drunk?
Re: [PATCH v2] security_syslog() should be called once only
Quoted 2 lines · Andrew Morton
So we run
security_syslog()for actions other thanopen()(of kmsg). Why?
Could you please clarify this question?
Linux kernel have reasonable default security policy and it's great. And at the same time kernel allows to override default behaviour and set custom security policy.
For example, to prohibit work on Saturday.
QA can use it for random failures generation.
Why not?
Quoted 1 line
Also, that
from_filehandling makes me cry.
...
Quoted 2 lines
One possible fix would be something like this, plus various fixups/audit:
I've prepared such patch and send it in separate letter.
Quoted 1 line
And
type' should be renamed toaction' for heavens sake.
IMHO 'type' and SYSLOG_ACTION_* was inherited from sys_syslog definition.
PATCH 1/1 check_syslog_permissions() cleanup
In reply to Andrew MortonPatch fixes drawbacks in heck_syslog_permissions() noticed by AKPM:
"from_file handling makes me cry.
That's not a boolean - it's an enumerated value with two values currently defined.
But the code in check_syslog_permissions() treats it as a boolean and also hardwires the knowledge that SYSLOG_FROM_PROC == 1 (or == true).
And the name is wrong: it should be called from_proc to match SYSLOG_FROM_PROC."
--- include/linux/syslog.h | 6 +++--- kernel/printk/printk.c | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-)
include/linux/syslog.h +3 -3
@@ -47,12 +47,12 @@#define SYSLOG_FROM_READER 0#define SYSLOG_FROM_PROC 1 -int do_syslog (int type,char __user *buf,int count,bool from_file); +int do_syslog (int type,char __user *buf,int count,int source);#ifdef CONFIG_PRINTK -int check_syslog_permissions (int type,bool from_file); +int check_syslog_permissions (int type,int source);#else -static inline int check_syslog_permissions (int type,bool from_file) +static inline int check_syslog_permissions (int type,int source) {return 0 ; }
kernel/printk/printk.c +5 -5
@@ -477,13 +477,13 @@ static int syslog_action_restricted(int type) type !=SYSLOG_ACTION_SIZE_BUFFER ; } -int check_syslog_permissions (int type,bool from_file) +int check_syslog_permissions (int type,int source) {/* * If this is from /proc/kmsg and we've already opened it, then we've * already done the capabilities checks at open time. */ -if (from_file && type !=SYSLOG_ACTION_OPEN ) +if (source ==SYSLOG_FROM_PROC && type !=SYSLOG_ACTION_OPEN ) goto ok;if (syslog_action_restricted (type)) {
@@ -1254,13 +1254,13 @@ static int syslog_print_all(char __user *buf, int size, bool clear)return len; } -int do_syslog (int type,char __user *buf,int len,bool from_file) +int do_syslog (int type,char __user *buf,int len,int source) {bool clear = false;static int saved_console_loglevel =LOGLEVEL_DEFAULT ;int error; - error =check_syslog_permissions (type, from_file); + error =check_syslog_permissions (type, source);if (error) goto out;
@@ -1343,7 +1343,7 @@ int do_syslog(int type, char __user *buf, int len, bool from_file) syslog_prev =0 ; syslog_partial =0 ; } -if (from_file) { +if (source ==SYSLOG_FROM_PROC ) {/* * Short-cut for poll(/"proc/kmsg") which simply checks * for pending data, not the size; return the count of
Signature · 1 line
1.9.1
Re: [PATCH v2] security_syslog() should be called once only
In reply to Vasily AverinQuoted 11 lines · On Sat, 30 May 2015 16:51:34 +0300 Vasily Averin <[email protected]> wrote:
Quoted 2 lines · Andrew Morton
So we run
security_syslog()for actions other thanopen()(of kmsg). Why?Could you please clarify this question?
Linux kernel have reasonable default security policy and it's great. And at the same time kernel allows to override default behaviour and set custom security policy.
For example, to prohibit work on Saturday.
QA can use it for random failures generation.
Why not?
This change:
: --- a/kernel/printk/printk.c~security_syslog-should-be-called-once-only : +++ a/kernel/printk/printk.c
: @@ -496,11 +496,11 @@ int check_syslog_permissions(int type, b
: * already done the capabilities checks at open time. : */ : if (from_file && type != SYSLOG_ACTION_OPEN)
: - return 0;
: + goto ok;
:
: ...
:
: } : return -EPERM; : }
: +ok:
: return security_syslog(type);
: }
Means that we will now call security_syslog() for SYSLOG_ACTION_CLOSE, SYSLOG_ACTION_READ, SYSLOG_ACTION_READ_ALL, etc.
That's new behaviour and it may be wrong. Why should check_syslog_permissions() call security_syslog() for anything other than SYSLOG_ACTION_OPEN?
Re: [PATCH v2] security_syslog() should be called once only
Quoted 35 lines · Andrew Morton
Quoted 11 lines · On Sat, 30 May 2015 16:51:34 +0300 Vasily Averin <[email protected]> wrote:
Quoted 2 lines · Andrew Morton
So we run
security_syslog()for actions other thanopen()(of kmsg). Why?Could you please clarify this question?
Linux kernel have reasonable default security policy and it's great. And at the same time kernel allows to override default behaviour and set custom security policy.
For example, to prohibit work on Saturday.
QA can use it for random failures generation.
Why not?This change:
: --- a/kernel/printk/printk.c~security_syslog-should-be-called-once-only : +++
a/kernel/printk/printk.c
: @@ -496,11 +496,11 @@ int check_syslog_permissions(int type, b: * already done the capabilities checks at open time. : */ : if (from_file && type != SYSLOG_ACTION_OPEN): - return 0;
: + goto ok;
:
: ...
:: } : return -EPERM; : }: +ok:
: returnsecurity_syslog(type);
: }
Quoted 6 lines
Means that we will now call
security_syslog()forSYSLOG_ACTION_CLOSE,SYSLOG_ACTION_READ,SYSLOG_ACTION_READ_ALL, etc.That's new behaviour and it may be wrong. Why should
check_syslog_permissions()callsecurity_syslog()for anything other thanSYSLOG_ACTION_OPEN?
But it isn't new behaviour.
Previously security_syslog() was called from do_syslog(), now it will be called from check_syslog_permissions()
from_file = true == SYSLOG_FROM_PROC is set in kmsg_open/release/read/pool() only. These functions use do_syslog() that had called security_syslog() right after return from check_syslog_permissions().
sys_syslog() calls this security hook for any action and does it long time ago.
The only place where behaviour is changed, where hook was _NOT_called is check_syslog_permissions(SYSLOG_ACTION_READ_ALL) calls from devkmsg_open() and pstore_check_syslog_permissions().
But they does it only if dmesg_restrict is set, that looks wrong for me, because dmesg_restict should add restrictions but do not remove existing ones.
So I do not see any new problems here.
Re: [PATCH v2] security_syslog() should be called once only
In reply to Andrew MortonQuoted 72 lines · Andrew Morton
Quoted 22 lines · On Sun, 24 May 2015 19:18:40 +0300 Vasily Averin <[email protected]> wrote:
v2: subject changed, patch comment modified
Fixes 637241a900cb ("kmsg: honor dmesg_restrict sysctl on /dev/kmsg")Final version of patch
637241a900cb("kmsg: honordmesg_restrictsysctl on/dev/kmsg") lost few hooks, as resultsecurity_syslog()are processed incorrectly:
- open of/dev/kmsgchecks syslog access permissions by usingcheck_syslog_permissions()wheresecurity_syslog()is not called ifdmesg_restrictis set.
- syslog syscall and/proc/kmsgcallsdo_syslog()
wheresecurity_syslogcan be executed twice
(insidecheck_syslog_permissions()and then directly indo_syslog())With this patch
security_syslog()is called once only in all syslog-related operations regardless ofdmesg_restrictvalue....
kernel/printk/printk.c int check_syslog_permissions(int type, bool from_file) · line 487
Quoted 5 lines
kernel/printk/printk.c +1
-1@@ -484,11 +484,11 @@ int check_syslog_permissions(int type, bool from_file)* already done the capabilities checks at open time. */ if (from_file && type !=SYSLOG_ACTION_OPEN ) -return 0 ; + goto ok;So we run
security_syslog()for actions other thanopen()(of kmsg). Why?Also, that
from_filehandling makes me cry.#define
SYSLOG_FROM_READER0
#defineSYSLOG_FROM_PROC1That's not a boolean - it's an enumerated value with two values currently defined.
But the code in
check_syslog_permissions()treats it as a boolean and also hardwires the knowledge thatSYSLOG_FROM_PROC== 1 (or ==true).And the name is wrong: it should be called
from_procto matchSYSLOG_FROM_PROC.One possible fix would be something like this, plus various fixups/audit:
kernel/printk/printk.c renamed from kernel/printk/printk.c~security_syslog-should-be-called-once-only-fix +2
-2@@ -489,13 +489,13 @@ static int syslog_action_restricted(int type !=SYSLOG_ACTION_SIZE_BUFFER ; } -int check_syslog_permissions (int type,bool from_file) +int check_syslog_permissions (int type,int source) {/* * If this is from /proc/kmsg and we've already opened it, then we've * already done the capabilities checks at open time. */ -if (from_file && type !=SYSLOG_ACTION_OPEN ) +if (source ==SYSLOG_FROM_PROC && type !=SYSLOG_ACTION_OPEN ) goto ok;if (syslog_action_restricted (type)) {_
Quoted 2 lines
And
type' should be renamed toaction' for heavens sake. Kees, were you drunk?
No, it's just been historically ugly code. I tried to improve it (before it was just using hard coded numbers) by adding the #defines for the actions.
The fundamental issue is that the syslog syscall interface has the ability to perform handle-less actions. We need to security-check all the syscall actions, but only the "open" on (at the time) /proc/kmsg. Adding devkmsg then gave us a third entry point, and it got even uglier.
So, the semantics for the security check depends on what was historically called "type" (but is better known by its SYSLOG_ACTION_* values). Linus wants security checking done on open where possible, so for files, the checking must be done against an implicit "SYSLOG_ACTION_OPEN". For the syscall, each action is individually checked.
With that in mind, what can we do to make this sensible, and cover /proc/kmsg, /dev/kmsg, and the syscall interface?
-Kees
Signature · 2 lines
Kees Cook Chrome OS Security