Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
1c0fe622
Commit
1c0fe622
authored
Jul 19, 2002
by
Greg Kroah-Hartman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
LSM: Enable the security framework. This includes basic task control hooks.
parent
2b15fe63
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
210 additions
and
169 deletions
+210
-169
Makefile
Makefile
+3
-2
arch/i386/config.in
arch/i386/config.in
+1
-0
arch/i386/kernel/entry.S
arch/i386/kernel/entry.S
+1
-1
arch/i386/kernel/ptrace.c
arch/i386/kernel/ptrace.c
+4
-0
fs/exec.c
fs/exec.c
+23
-48
include/linux/binfmts.h
include/linux/binfmts.h
+1
-0
include/linux/sched.h
include/linux/sched.h
+6
-4
init/main.c
init/main.c
+2
-0
kernel/capability.c
kernel/capability.c
+9
-10
kernel/exit.c
kernel/exit.c
+7
-4
kernel/fork.c
kernel/fork.c
+11
-2
kernel/kmod.c
kernel/kmod.c
+1
-1
kernel/ptrace.c
kernel/ptrace.c
+6
-2
kernel/sched.c
kernel/sched.c
+34
-7
kernel/signal.c
kernel/signal.c
+3
-0
kernel/sys.c
kernel/sys.c
+91
-87
kernel/uid16.c
kernel/uid16.c
+7
-1
No files found.
Makefile
View file @
1c0fe622
...
...
@@ -157,7 +157,8 @@ objtree := $(TOPDIR)
export
srctree
objtree
SUBDIRS
:=
init kernel mm fs ipc lib drivers sound net
SUBDIRS
:=
init kernel mm fs ipc lib drivers sound net security
noconfig_targets
:=
xconfig menuconfig config oldconfig randconfig
\
defconfig allyesconfig allnoconfig allmodconfig
\
...
...
@@ -223,7 +224,7 @@ endif
# ---------------------------------------------------------------------------
INIT
:=
init/init.o
CORE_FILES
:=
kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o
CORE_FILES
:=
kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o
security/built-in.o
LIBS
:=
lib/lib.a
DRIVERS
:=
drivers/built-in.o sound/sound.o
NETWORKS
:=
net/network.o
...
...
arch/i386/config.in
View file @
1c0fe622
...
...
@@ -423,4 +423,5 @@ fi
endmenu
source security/Config.in
source lib/Config.in
arch/i386/kernel/entry.S
View file @
1c0fe622
...
...
@@ -744,7 +744,7 @@ ENTRY(sys_call_table)
.
long
sys_getdents64
/*
220
*/
.
long
sys_fcntl64
.
long
sys_ni_syscall
/*
reserved
for
TUX
*/
.
long
sys_
ni_syscall
/*
reserved
for
Security
*/
.
long
sys_
security
/*
reserved
for
Security
*/
.
long
sys_gettid
.
long
sys_readahead
/*
225
*/
.
long
sys_setxattr
...
...
arch/i386/kernel/ptrace.c
View file @
1c0fe622
...
...
@@ -13,6 +13,7 @@
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>
#include <linux/security.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
...
...
@@ -159,6 +160,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
/* are we already being traced? */
if
(
current
->
ptrace
&
PT_PTRACED
)
goto
out
;
ret
=
security_ops
->
ptrace
(
current
->
parent
,
current
);
if
(
ret
)
goto
out
;
/* set the ptrace bit in the process flags. */
current
->
ptrace
|=
PT_PTRACED
;
ret
=
0
;
...
...
fs/exec.c
View file @
1c0fe622
...
...
@@ -623,6 +623,7 @@ int prepare_binprm(struct linux_binprm *bprm)
{
int
mode
;
struct
inode
*
inode
=
bprm
->
file
->
f_dentry
->
d_inode
;
int
retval
;
mode
=
inode
->
i_mode
;
/*
...
...
@@ -652,27 +653,10 @@ int prepare_binprm(struct linux_binprm *bprm)
bprm
->
e_gid
=
inode
->
i_gid
;
}
/* We don't have VFS support for capabilities yet */
cap_clear
(
bprm
->
cap_inheritable
);
cap_clear
(
bprm
->
cap_permitted
);
cap_clear
(
bprm
->
cap_effective
);
/* To support inheritance of root-permissions and suid-root
* executables under compatibility mode, we raise all three
* capability sets for the file.
*
* If only the real uid is 0, we only raise the inheritable
* and permitted sets of the executable file.
*/
if
(
!
issecure
(
SECURE_NOROOT
))
{
if
(
bprm
->
e_uid
==
0
||
current
->
uid
==
0
)
{
cap_set_full
(
bprm
->
cap_inheritable
);
cap_set_full
(
bprm
->
cap_permitted
);
}
if
(
bprm
->
e_uid
==
0
)
cap_set_full
(
bprm
->
cap_effective
);
}
/* fill in binprm security blob */
retval
=
security_ops
->
bprm_set_security
(
bprm
);
if
(
retval
)
return
retval
;
memset
(
bprm
->
buf
,
0
,
BINPRM_BUF_SIZE
);
return
kernel_read
(
bprm
->
file
,
0
,
bprm
->
buf
,
BINPRM_BUF_SIZE
);
...
...
@@ -695,16 +679,9 @@ int prepare_binprm(struct linux_binprm *bprm)
void
compute_creds
(
struct
linux_binprm
*
bprm
)
{
kernel_cap_t
new_permitted
,
working
;
int
do_unlock
=
0
;
new_permitted
=
cap_intersect
(
bprm
->
cap_permitted
,
cap_bset
);
working
=
cap_intersect
(
bprm
->
cap_inheritable
,
current
->
cap_inheritable
);
new_permitted
=
cap_combine
(
new_permitted
,
working
);
if
(
bprm
->
e_uid
!=
current
->
uid
||
bprm
->
e_gid
!=
current
->
gid
||
!
cap_issubset
(
new_permitted
,
current
->
cap_permitted
))
{
if
(
bprm
->
e_uid
!=
current
->
uid
||
bprm
->
e_gid
!=
current
->
gid
)
{
current
->
mm
->
dumpable
=
0
;
lock_kernel
();
...
...
@@ -716,32 +693,17 @@ void compute_creds(struct linux_binprm *bprm)
bprm
->
e_uid
=
current
->
uid
;
bprm
->
e_gid
=
current
->
gid
;
}
if
(
!
capable
(
CAP_SETPCAP
))
{
new_permitted
=
cap_intersect
(
new_permitted
,
current
->
cap_permitted
);
}
}
do_unlock
=
1
;
}
/* For init, we want to retain the capabilities set
* in the init_task struct. Thus we skip the usual
* capability rules */
if
(
current
->
pid
!=
1
)
{
current
->
cap_permitted
=
new_permitted
;
current
->
cap_effective
=
cap_intersect
(
new_permitted
,
bprm
->
cap_effective
);
}
/* AUD: Audit candidate if current->cap_effective is set */
current
->
suid
=
current
->
euid
=
current
->
fsuid
=
bprm
->
e_uid
;
current
->
sgid
=
current
->
egid
=
current
->
fsgid
=
bprm
->
e_gid
;
if
(
do_unlock
)
unlock_kernel
();
current
->
keep_capabilities
=
0
;
security_ops
->
bprm_compute_creds
(
bprm
);
}
...
...
@@ -811,6 +773,10 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
}
}
#endif
retval
=
security_ops
->
bprm_check_security
(
bprm
);
if
(
retval
)
return
retval
;
/* kernel module loader fixup */
/* so we don't try to load run modprobe in kernel space. */
set_fs
(
USER_DS
);
...
...
@@ -887,7 +853,7 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs
bprm
.
sh_bang
=
0
;
bprm
.
loader
=
0
;
bprm
.
exec
=
0
;
bprm
.
security
=
NULL
;
bprm
.
mm
=
mm_alloc
();
retval
=
-
ENOMEM
;
if
(
!
bprm
.
mm
)
...
...
@@ -905,6 +871,10 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs
if
((
retval
=
bprm
.
envc
)
<
0
)
goto
out_mm
;
retval
=
security_ops
->
bprm_alloc_security
(
&
bprm
);
if
(
retval
)
goto
out
;
retval
=
prepare_binprm
(
&
bprm
);
if
(
retval
<
0
)
goto
out
;
...
...
@@ -923,9 +893,11 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs
goto
out
;
retval
=
search_binary_handler
(
&
bprm
,
regs
);
if
(
retval
>=
0
)
if
(
retval
>=
0
)
{
/* execve success */
security_ops
->
bprm_free_security
(
&
bprm
);
return
retval
;
}
out:
/* Something went wrong, return the inode and free the argument pages*/
...
...
@@ -935,6 +907,9 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs
__free_page
(
page
);
}
if
(
bprm
.
security
)
security_ops
->
bprm_free_security
(
&
bprm
);
out_mm:
mmdrop
(
bprm
.
mm
);
...
...
include/linux/binfmts.h
View file @
1c0fe622
...
...
@@ -28,6 +28,7 @@ struct linux_binprm{
struct
file
*
file
;
int
e_uid
,
e_gid
;
kernel_cap_t
cap_inheritable
,
cap_permitted
,
cap_effective
;
void
*
security
;
int
argc
,
envc
;
char
*
filename
;
/* Name of binary */
unsigned
long
loader
,
exec
;
...
...
include/linux/sched.h
View file @
1c0fe622
...
...
@@ -354,6 +354,8 @@ struct task_struct {
void
*
notifier_data
;
sigset_t
*
notifier_mask
;
void
*
security
;
/* Thread group tracking */
u32
parent_exec_id
;
u32
self_exec_id
;
...
...
@@ -587,10 +589,9 @@ extern int request_irq(unsigned int,
unsigned
long
,
const
char
*
,
void
*
);
extern
void
free_irq
(
unsigned
int
,
void
*
);
/*
* capable() checks for a particular capability.
* See include/linux/capability.h for defined capabilities.
*/
/* capable prototype and code moved to security.[hc] */
#include <linux/security.h>
#if 0
static inline int capable(int cap)
{
if (cap_raised(current->cap_effective, cap)) {
...
...
@@ -599,6 +600,7 @@ static inline int capable(int cap)
}
return 0;
}
#endif /* if 0 */
/*
* Routines for handling mm_structs
...
...
init/main.c
View file @
1c0fe622
...
...
@@ -29,6 +29,7 @@
#include <linux/tty.h>
#include <linux/percpu.h>
#include <linux/kernel_stat.h>
#include <linux/security.h>
#include <asm/io.h>
#include <asm/bugs.h>
...
...
@@ -390,6 +391,7 @@ asmlinkage void __init start_kernel(void)
fork_init
(
mempages
);
proc_caches_init
();
security_scaffolding_startup
();
buffer_init
();
vfs_caches_init
(
mempages
);
radix_tree_init
();
...
...
kernel/capability.c
View file @
1c0fe622
...
...
@@ -63,6 +63,7 @@ asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
data
.
permitted
=
cap_t
(
target
->
cap_permitted
);
data
.
inheritable
=
cap_t
(
target
->
cap_inheritable
);
data
.
effective
=
cap_t
(
target
->
cap_effective
);
ret
=
security_ops
->
capget
(
target
,
&
data
.
effective
,
&
data
.
inheritable
,
&
data
.
permitted
);
out:
read_unlock
(
&
tasklist_lock
);
...
...
@@ -87,9 +88,7 @@ static inline void cap_set_pg(int pgrp, kernel_cap_t *effective,
for_each_task
(
target
)
{
if
(
target
->
pgrp
!=
pgrp
)
continue
;
target
->
cap_effective
=
*
effective
;
target
->
cap_inheritable
=
*
inheritable
;
target
->
cap_permitted
=
*
permitted
;
security_ops
->
capset_set
(
target
,
effective
,
inheritable
,
permitted
);
}
}
...
...
@@ -106,9 +105,7 @@ static inline void cap_set_all(kernel_cap_t *effective,
for_each_task
(
target
)
{
if
(
target
==
current
||
target
->
pid
==
1
)
continue
;
target
->
cap_effective
=
*
effective
;
target
->
cap_inheritable
=
*
inheritable
;
target
->
cap_permitted
=
*
permitted
;
security_ops
->
capset_set
(
target
,
effective
,
inheritable
,
permitted
);
}
}
...
...
@@ -166,7 +163,9 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
ret
=
-
EPERM
;
/* verify restrictions on target's new Inheritable set */
if
(
security_ops
->
capset_check
(
target
,
&
effective
,
&
inheritable
,
&
permitted
))
goto
out
;
if
(
!
cap_issubset
(
inheritable
,
cap_combine
(
target
->
cap_inheritable
,
current
->
cap_permitted
)))
goto
out
;
...
...
@@ -182,6 +181,8 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
ret
=
0
;
/* having verified that the proposed changes are legal,
we now put them into effect. */
if
(
pid
<
0
)
{
if
(
pid
==
-
1
)
/* all procs other than current and init */
cap_set_all
(
&
effective
,
&
inheritable
,
&
permitted
);
...
...
@@ -189,9 +190,7 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
else
/* all procs in process group */
cap_set_pg
(
-
pid
,
&
effective
,
&
inheritable
,
&
permitted
);
}
else
{
target
->
cap_effective
=
effective
;
target
->
cap_inheritable
=
inheritable
;
target
->
cap_permitted
=
permitted
;
security_ops
->
capset_set
(
target
,
&
effective
,
&
inheritable
,
&
permitted
);
}
out:
...
...
kernel/exit.c
View file @
1c0fe622
...
...
@@ -14,6 +14,7 @@
#include <linux/personality.h>
#include <linux/tty.h>
#include <linux/namespace.h>
#include <linux/security.h>
#include <linux/acct.h>
#include <linux/file.h>
#include <linux/binfmts.h>
...
...
@@ -61,6 +62,7 @@ static void release_task(struct task_struct * p)
wait_task_inactive
(
p
);
#endif
atomic_dec
(
&
p
->
user
->
processes
);
security_ops
->
task_free_security
(
p
);
free_uid
(
p
->
user
);
unhash_process
(
p
);
...
...
@@ -187,10 +189,7 @@ void reparent_to_init(void)
/* cpus_allowed? */
/* rt_priority? */
/* signals? */
current
->
cap_effective
=
CAP_INIT_EFF_SET
;
current
->
cap_inheritable
=
CAP_INIT_INH_SET
;
current
->
cap_permitted
=
CAP_FULL_SET
;
current
->
keep_capabilities
=
0
;
security_ops
->
task_reparent_to_init
(
current
);
memcpy
(
current
->
rlim
,
init_task
.
rlim
,
sizeof
(
*
(
current
->
rlim
)));
current
->
user
=
INIT_USER
;
...
...
@@ -625,6 +624,10 @@ asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struc
if
(((
p
->
exit_signal
!=
SIGCHLD
)
^
((
options
&
__WCLONE
)
!=
0
))
&&
!
(
options
&
__WALL
))
continue
;
if
(
security_ops
->
task_wait
(
p
))
continue
;
flag
=
1
;
switch
(
p
->
state
)
{
case
TASK_STOPPED
:
...
...
kernel/fork.c
View file @
1c0fe622
...
...
@@ -24,7 +24,7 @@
#include <linux/file.h>
#include <linux/binfmts.h>
#include <linux/fs.h>
#include <linux/
mm
.h>
#include <linux/
security
.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
...
...
@@ -618,6 +618,10 @@ struct task_struct *do_fork(unsigned long clone_flags,
if
((
clone_flags
&
(
CLONE_NEWNS
|
CLONE_FS
))
==
(
CLONE_NEWNS
|
CLONE_FS
))
return
ERR_PTR
(
-
EINVAL
);
retval
=
security_ops
->
task_create
(
clone_flags
);
if
(
retval
)
goto
fork_out
;
retval
=
-
ENOMEM
;
p
=
dup_task_struct
(
current
);
if
(
!
p
)
...
...
@@ -697,13 +701,16 @@ struct task_struct *do_fork(unsigned long clone_flags,
p
->
array
=
NULL
;
p
->
lock_depth
=
-
1
;
/* -1 = no lock */
p
->
start_time
=
jiffies
;
p
->
security
=
NULL
;
INIT_LIST_HEAD
(
&
p
->
local_pages
);
retval
=
-
ENOMEM
;
if
(
security_ops
->
task_alloc_security
(
p
))
goto
bad_fork_cleanup
;
/* copy all the process information */
if
(
copy_semundo
(
clone_flags
,
p
))
goto
bad_fork_cleanup
;
goto
bad_fork_cleanup
_security
;
if
(
copy_files
(
clone_flags
,
p
))
goto
bad_fork_cleanup_semundo
;
if
(
copy_fs
(
clone_flags
,
p
))
...
...
@@ -812,6 +819,8 @@ struct task_struct *do_fork(unsigned long clone_flags,
exit_files
(
p
);
/* blocking */
bad_fork_cleanup_semundo:
exit_semundo
(
p
);
bad_fork_cleanup_security:
security_ops
->
task_free_security
(
p
);
bad_fork_cleanup:
put_exec_domain
(
p
->
thread_info
->
exec_domain
);
if
(
p
->
binfmt
&&
p
->
binfmt
->
module
)
...
...
kernel/kmod.c
View file @
1c0fe622
...
...
@@ -134,7 +134,7 @@ int exec_usermodehelper(char *program_path, char *argv[], char *envp[])
/* Give kmod all effective privileges.. */
curtask
->
euid
=
curtask
->
fsuid
=
0
;
curtask
->
egid
=
curtask
->
fsgid
=
0
;
cap_set_full
(
curtask
->
cap_effective
);
security_ops
->
task_kmod_set_label
(
);
/* Allow execve args to be in kernel space. */
set_fs
(
KERNEL_DS
);
...
...
kernel/ptrace.c
View file @
1c0fe622
...
...
@@ -41,7 +41,9 @@ int ptrace_check_attach(struct task_struct *child, int kill)
int
ptrace_attach
(
struct
task_struct
*
task
)
{
int
retval
;
task_lock
(
task
);
retval
=
-
EPERM
;
if
(
task
->
pid
<=
1
)
goto
bad
;
if
(
task
==
current
)
...
...
@@ -53,7 +55,6 @@ int ptrace_attach(struct task_struct *task)
(
current
->
uid
!=
task
->
uid
)
||
(
current
->
gid
!=
task
->
egid
)
||
(
current
->
gid
!=
task
->
sgid
)
||
(
!
cap_issubset
(
task
->
cap_permitted
,
current
->
cap_permitted
))
||
(
current
->
gid
!=
task
->
gid
))
&&
!
capable
(
CAP_SYS_PTRACE
))
goto
bad
;
rmb
();
...
...
@@ -62,6 +63,9 @@ int ptrace_attach(struct task_struct *task)
/* the same process cannot be attached many times */
if
(
task
->
ptrace
&
PT_PTRACED
)
goto
bad
;
retval
=
security_ops
->
ptrace
(
current
,
task
);
if
(
retval
)
goto
bad
;
/* Go */
task
->
ptrace
|=
PT_PTRACED
;
...
...
@@ -82,7 +86,7 @@ int ptrace_attach(struct task_struct *task)
bad:
task_unlock
(
task
);
return
-
EPERM
;
return
retval
;
}
int
ptrace_detach
(
struct
task_struct
*
child
,
unsigned
int
data
)
...
...
kernel/sched.c
View file @
1c0fe622
...
...
@@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/kernel_stat.h>
#include <linux/security.h>
/*
* Convert user-nice values [ -20 ... 0 ... 19 ]
...
...
@@ -1123,6 +1124,7 @@ void set_user_nice(task_t *p, long nice)
asmlinkage
long
sys_nice
(
int
increment
)
{
int
retval
;
long
nice
;
/*
...
...
@@ -1144,6 +1146,11 @@ asmlinkage long sys_nice(int increment)
nice
=
-
20
;
if
(
nice
>
19
)
nice
=
19
;
retval
=
security_ops
->
task_setnice
(
current
,
nice
);
if
(
retval
)
return
retval
;
set_user_nice
(
current
,
nice
);
return
0
;
}
...
...
@@ -1236,6 +1243,10 @@ static int setscheduler(pid_t pid, int policy, struct sched_param *param)
!
capable
(
CAP_SYS_NICE
))
goto
out_unlock
;
retval
=
security_ops
->
task_setscheduler
(
p
,
policy
,
&
lp
);
if
(
retval
)
goto
out_unlock
;
array
=
p
->
array
;
if
(
array
)
deactivate_task
(
p
,
task_rq
(
p
));
...
...
@@ -1280,8 +1291,11 @@ asmlinkage long sys_sched_getscheduler(pid_t pid)
retval
=
-
ESRCH
;
read_lock
(
&
tasklist_lock
);
p
=
find_process_by_pid
(
pid
);
if
(
p
)
retval
=
p
->
policy
;
if
(
p
)
{
retval
=
security_ops
->
task_getscheduler
(
p
);
if
(
!
retval
)
retval
=
p
->
policy
;
}
read_unlock
(
&
tasklist_lock
);
out_nounlock:
...
...
@@ -1302,6 +1316,11 @@ asmlinkage long sys_sched_getparam(pid_t pid, struct sched_param *param)
retval
=
-
ESRCH
;
if
(
!
p
)
goto
out_unlock
;
retval
=
security_ops
->
task_getscheduler
(
p
);
if
(
retval
)
goto
out_unlock
;
lp
.
sched_priority
=
p
->
rt_priority
;
read_unlock
(
&
tasklist_lock
);
...
...
@@ -1509,14 +1528,22 @@ asmlinkage long sys_sched_rr_get_interval(pid_t pid, struct timespec *interval)
retval
=
-
ESRCH
;
read_lock
(
&
tasklist_lock
);
p
=
find_process_by_pid
(
pid
);
if
(
p
)
jiffies_to_timespec
(
p
->
policy
&
SCHED_FIFO
?
0
:
TASK_TIMESLICE
(
p
),
&
t
);
if
(
!
p
)
goto
out_unlock
;
retval
=
security_ops
->
task_getscheduler
(
p
);
if
(
retval
)
goto
out_unlock
;
jiffies_to_timespec
(
p
->
policy
&
SCHED_FIFO
?
0
:
TASK_TIMESLICE
(
p
),
&
t
);
read_unlock
(
&
tasklist_lock
);
if
(
p
)
retval
=
copy_to_user
(
interval
,
&
t
,
sizeof
(
t
))
?
-
EFAULT
:
0
;
retval
=
copy_to_user
(
interval
,
&
t
,
sizeof
(
t
))
?
-
EFAULT
:
0
;
out_nounlock:
return
retval
;
out_unlock:
read_unlock
(
&
tasklist_lock
);
return
retval
;
}
static
void
show_task
(
task_t
*
p
)
...
...
kernel/signal.c
View file @
1c0fe622
...
...
@@ -548,6 +548,9 @@ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
ret
=
-
EPERM
;
if
(
bad_signal
(
sig
,
info
,
t
))
goto
out_nolock
;
ret
=
security_ops
->
task_kill
(
t
,
info
,
sig
);
if
(
ret
)
goto
out_nolock
;
/* The null signal is a permissions and process existence probe.
No signal is actually delivered. Same goes for zombies. */
...
...
kernel/sys.c
View file @
1c0fe622
...
...
@@ -19,6 +19,7 @@
#include <linux/tqueue.h>
#include <linux/device.h>
#include <linux/times.h>
#include <linux/security.h>
#include <asm/uaccess.h>
#include <asm/io.h>
...
...
@@ -234,6 +235,7 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
read_lock
(
&
tasklist_lock
);
for_each_task
(
p
)
{
int
no_nice
;
if
(
!
proc_sel
(
p
,
which
,
who
))
continue
;
if
(
p
->
uid
!=
current
->
euid
&&
...
...
@@ -243,10 +245,17 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
}
if
(
error
==
-
ESRCH
)
error
=
0
;
if
(
niceval
<
task_nice
(
p
)
&&
!
capable
(
CAP_SYS_NICE
))
if
(
niceval
<
task_nice
(
p
)
&&
!
capable
(
CAP_SYS_NICE
))
{
error
=
-
EACCES
;
else
set_user_nice
(
p
,
niceval
);
continue
;
}
no_nice
=
security_ops
->
task_setnice
(
p
,
niceval
);
if
(
no_nice
)
{
error
=
no_nice
;
continue
;
}
set_user_nice
(
p
,
niceval
);
}
read_unlock
(
&
tasklist_lock
);
...
...
@@ -416,6 +425,11 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
int
old_egid
=
current
->
egid
;
int
new_rgid
=
old_rgid
;
int
new_egid
=
old_egid
;
int
retval
;
retval
=
security_ops
->
task_setgid
(
rgid
,
egid
,
(
gid_t
)
-
1
,
LSM_SETID_RE
);
if
(
retval
)
return
retval
;
if
(
rgid
!=
(
gid_t
)
-
1
)
{
if
((
old_rgid
==
rgid
)
||
...
...
@@ -457,6 +471,11 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
asmlinkage
long
sys_setgid
(
gid_t
gid
)
{
int
old_egid
=
current
->
egid
;
int
retval
;
retval
=
security_ops
->
task_setgid
(
gid
,
(
gid_t
)
-
1
,
(
gid_t
)
-
1
,
LSM_SETID_ID
);
if
(
retval
)
return
retval
;
if
(
capable
(
CAP_SETGID
))
{
...
...
@@ -481,52 +500,6 @@ asmlinkage long sys_setgid(gid_t gid)
return
0
;
}
/*
* cap_emulate_setxuid() fixes the effective / permitted capabilities of
* a process after a call to setuid, setreuid, or setresuid.
*
* 1) When set*uiding _from_ one of {r,e,s}uid == 0 _to_ all of
* {r,e,s}uid != 0, the permitted and effective capabilities are
* cleared.
*
* 2) When set*uiding _from_ euid == 0 _to_ euid != 0, the effective
* capabilities of the process are cleared.
*
* 3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective
* capabilities are set to the permitted capabilities.
*
* fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should
* never happen.
*
* -astor
*
* cevans - New behaviour, Oct '99
* A process may, via prctl(), elect to keep its capabilities when it
* calls setuid() and switches away from uid==0. Both permitted and
* effective sets will be retained.
* Without this change, it was impossible for a daemon to drop only some
* of its privilege. The call to setuid(!=0) would drop all privileges!
* Keeping uid 0 is not an option because uid 0 owns too many vital
* files..
* Thanks to Olaf Kirch and Peter Benie for spotting this.
*/
static
inline
void
cap_emulate_setxuid
(
int
old_ruid
,
int
old_euid
,
int
old_suid
)
{
if
((
old_ruid
==
0
||
old_euid
==
0
||
old_suid
==
0
)
&&
(
current
->
uid
!=
0
&&
current
->
euid
!=
0
&&
current
->
suid
!=
0
)
&&
!
current
->
keep_capabilities
)
{
cap_clear
(
current
->
cap_permitted
);
cap_clear
(
current
->
cap_effective
);
}
if
(
old_euid
==
0
&&
current
->
euid
!=
0
)
{
cap_clear
(
current
->
cap_effective
);
}
if
(
old_euid
!=
0
&&
current
->
euid
==
0
)
{
current
->
cap_effective
=
current
->
cap_permitted
;
}
}
static
int
set_user
(
uid_t
new_ruid
,
int
dumpclear
)
{
struct
user_struct
*
new_user
,
*
old_user
;
...
...
@@ -572,6 +545,11 @@ static int set_user(uid_t new_ruid, int dumpclear)
asmlinkage
long
sys_setreuid
(
uid_t
ruid
,
uid_t
euid
)
{
int
old_ruid
,
old_euid
,
old_suid
,
new_ruid
,
new_euid
;
int
retval
;
retval
=
security_ops
->
task_setuid
(
ruid
,
euid
,
(
uid_t
)
-
1
,
LSM_SETID_RE
);
if
(
retval
)
return
retval
;
new_ruid
=
old_ruid
=
current
->
uid
;
new_euid
=
old_euid
=
current
->
euid
;
...
...
@@ -608,11 +586,7 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
current
->
suid
=
current
->
euid
;
current
->
fsuid
=
current
->
euid
;
if
(
!
issecure
(
SECURE_NO_SETUID_FIXUP
))
{
cap_emulate_setxuid
(
old_ruid
,
old_euid
,
old_suid
);
}
return
0
;
return
security_ops
->
task_post_setuid
(
old_ruid
,
old_euid
,
old_suid
,
LSM_SETID_RE
);
}
...
...
@@ -632,6 +606,11 @@ asmlinkage long sys_setuid(uid_t uid)
{
int
old_euid
=
current
->
euid
;
int
old_ruid
,
old_suid
,
new_ruid
,
new_suid
;
int
retval
;
retval
=
security_ops
->
task_setuid
(
uid
,
(
uid_t
)
-
1
,
(
uid_t
)
-
1
,
LSM_SETID_ID
);
if
(
retval
)
return
retval
;
old_ruid
=
new_ruid
=
current
->
uid
;
old_suid
=
current
->
suid
;
...
...
@@ -652,11 +631,7 @@ asmlinkage long sys_setuid(uid_t uid)
current
->
fsuid
=
current
->
euid
=
uid
;
current
->
suid
=
new_suid
;
if
(
!
issecure
(
SECURE_NO_SETUID_FIXUP
))
{
cap_emulate_setxuid
(
old_ruid
,
old_euid
,
old_suid
);
}
return
0
;
return
security_ops
->
task_post_setuid
(
old_ruid
,
old_euid
,
old_suid
,
LSM_SETID_ID
);
}
...
...
@@ -669,6 +644,11 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
int
old_ruid
=
current
->
uid
;
int
old_euid
=
current
->
euid
;
int
old_suid
=
current
->
suid
;
int
retval
;
retval
=
security_ops
->
task_setuid
(
ruid
,
euid
,
suid
,
LSM_SETID_RES
);
if
(
retval
)
return
retval
;
if
(
!
capable
(
CAP_SETUID
))
{
if
((
ruid
!=
(
uid_t
)
-
1
)
&&
(
ruid
!=
current
->
uid
)
&&
...
...
@@ -697,11 +677,7 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
if
(
suid
!=
(
uid_t
)
-
1
)
current
->
suid
=
suid
;
if
(
!
issecure
(
SECURE_NO_SETUID_FIXUP
))
{
cap_emulate_setxuid
(
old_ruid
,
old_euid
,
old_suid
);
}
return
0
;
return
security_ops
->
task_post_setuid
(
old_ruid
,
old_euid
,
old_suid
,
LSM_SETID_RES
);
}
asmlinkage
long
sys_getresuid
(
uid_t
*
ruid
,
uid_t
*
euid
,
uid_t
*
suid
)
...
...
@@ -720,6 +696,12 @@ asmlinkage long sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
*/
asmlinkage
long
sys_setresgid
(
gid_t
rgid
,
gid_t
egid
,
gid_t
sgid
)
{
int
retval
;
retval
=
security_ops
->
task_setgid
(
rgid
,
egid
,
sgid
,
LSM_SETID_RES
);
if
(
retval
)
return
retval
;
if
(
!
capable
(
CAP_SETGID
))
{
if
((
rgid
!=
(
gid_t
)
-
1
)
&&
(
rgid
!=
current
->
gid
)
&&
(
rgid
!=
current
->
egid
)
&&
(
rgid
!=
current
->
sgid
))
...
...
@@ -768,6 +750,11 @@ asmlinkage long sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
asmlinkage
long
sys_setfsuid
(
uid_t
uid
)
{
int
old_fsuid
;
int
retval
;
retval
=
security_ops
->
task_setuid
(
uid
,
(
uid_t
)
-
1
,
(
uid_t
)
-
1
,
LSM_SETID_FS
);
if
(
retval
)
return
retval
;
old_fsuid
=
current
->
fsuid
;
if
(
uid
==
current
->
uid
||
uid
==
current
->
euid
||
...
...
@@ -782,24 +769,9 @@ asmlinkage long sys_setfsuid(uid_t uid)
current
->
fsuid
=
uid
;
}
/* We emulate fsuid by essentially doing a scaled-down version
* of what we did in setresuid and friends. However, we only
* operate on the fs-specific bits of the process' effective
* capabilities
*
* FIXME - is fsuser used for all CAP_FS_MASK capabilities?
* if not, we might be a bit too harsh here.
*/
if
(
!
issecure
(
SECURE_NO_SETUID_FIXUP
))
{
if
(
old_fsuid
==
0
&&
current
->
fsuid
!=
0
)
{
cap_t
(
current
->
cap_effective
)
&=
~
CAP_FS_MASK
;
}
if
(
old_fsuid
!=
0
&&
current
->
fsuid
==
0
)
{
cap_t
(
current
->
cap_effective
)
|=
(
cap_t
(
current
->
cap_permitted
)
&
CAP_FS_MASK
);
}
}
retval
=
security_ops
->
task_post_setuid
(
old_fsuid
,
(
uid_t
)
-
1
,
(
uid_t
)
-
1
,
LSM_SETID_FS
);
if
(
retval
)
return
retval
;
return
old_fsuid
;
}
...
...
@@ -810,6 +782,11 @@ asmlinkage long sys_setfsuid(uid_t uid)
asmlinkage
long
sys_setfsgid
(
gid_t
gid
)
{
int
old_fsgid
;
int
retval
;
retval
=
security_ops
->
task_setgid
(
gid
,
(
gid_t
)
-
1
,
(
gid_t
)
-
1
,
LSM_SETID_FS
);
if
(
retval
)
return
retval
;
old_fsgid
=
current
->
fsgid
;
if
(
gid
==
current
->
gid
||
gid
==
current
->
egid
||
...
...
@@ -904,6 +881,10 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
}
ok_pgid:
err
=
security_ops
->
task_setpgid
(
p
,
pgid
);
if
(
err
)
goto
out
;
p
->
pgrp
=
pgid
;
err
=
0
;
out:
...
...
@@ -924,8 +905,11 @@ asmlinkage long sys_getpgid(pid_t pid)
p
=
find_task_by_pid
(
pid
);
retval
=
-
ESRCH
;
if
(
p
)
retval
=
p
->
pgrp
;
if
(
p
)
{
retval
=
security_ops
->
task_getpgid
(
p
);
if
(
!
retval
)
retval
=
p
->
pgrp
;
}
read_unlock
(
&
tasklist_lock
);
return
retval
;
}
...
...
@@ -949,8 +933,11 @@ asmlinkage long sys_getsid(pid_t pid)
p
=
find_task_by_pid
(
pid
);
retval
=
-
ESRCH
;
if
(
p
)
retval
=
p
->
session
;
if
(
p
)
{
retval
=
security_ops
->
task_getsid
(
p
);
if
(
!
retval
)
retval
=
p
->
session
;
}
read_unlock
(
&
tasklist_lock
);
return
retval
;
}
...
...
@@ -1008,12 +995,19 @@ asmlinkage long sys_getgroups(int gidsetsize, gid_t *grouplist)
asmlinkage
long
sys_setgroups
(
int
gidsetsize
,
gid_t
*
grouplist
)
{
gid_t
groups
[
NGROUPS
];
int
retval
;
if
(
!
capable
(
CAP_SETGID
))
return
-
EPERM
;
if
((
unsigned
)
gidsetsize
>
NGROUPS
)
return
-
EINVAL
;
if
(
copy_from_user
(
current
->
groups
,
grouplist
,
gidsetsize
*
sizeof
(
gid_t
)))
if
(
copy_from_user
(
groups
,
grouplist
,
gidsetsize
*
sizeof
(
gid_t
)))
return
-
EFAULT
;
retval
=
security_ops
->
task_setgroups
(
gidsetsize
,
groups
);
if
(
retval
)
return
retval
;
memcpy
(
current
->
groups
,
groups
,
gidsetsize
*
sizeof
(
gid_t
));
current
->
ngroups
=
gidsetsize
;
return
0
;
}
...
...
@@ -1158,6 +1152,7 @@ asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit *rlim)
asmlinkage
long
sys_setrlimit
(
unsigned
int
resource
,
struct
rlimit
*
rlim
)
{
struct
rlimit
new_rlim
,
*
old_rlim
;
int
retval
;
if
(
resource
>=
RLIM_NLIMITS
)
return
-
EINVAL
;
...
...
@@ -1172,6 +1167,11 @@ asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim)
if
(
new_rlim
.
rlim_cur
>
NR_OPEN
||
new_rlim
.
rlim_max
>
NR_OPEN
)
return
-
EPERM
;
}
retval
=
security_ops
->
task_setrlimit
(
resource
,
&
new_rlim
);
if
(
retval
)
return
retval
;
*
old_rlim
=
new_rlim
;
return
0
;
}
...
...
@@ -1243,6 +1243,10 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
int
error
=
0
;
int
sig
;
error
=
security_ops
->
task_prctl
(
option
,
arg2
,
arg3
,
arg4
,
arg5
);
if
(
error
)
return
error
;
switch
(
option
)
{
case
PR_SET_PDEATHSIG
:
sig
=
arg2
;
...
...
kernel/uid16.c
View file @
1c0fe622
...
...
@@ -12,6 +12,7 @@
#include <linux/prctl.h>
#include <linux/init.h>
#include <linux/highuid.h>
#include <linux/security.h>
#include <asm/uaccess.h>
...
...
@@ -128,6 +129,7 @@ asmlinkage long sys_getgroups16(int gidsetsize, old_gid_t *grouplist)
asmlinkage
long
sys_setgroups16
(
int
gidsetsize
,
old_gid_t
*
grouplist
)
{
old_gid_t
groups
[
NGROUPS
];
gid_t
new_groups
[
NGROUPS
];
int
i
;
if
(
!
capable
(
CAP_SETGID
))
...
...
@@ -137,7 +139,11 @@ asmlinkage long sys_setgroups16(int gidsetsize, old_gid_t *grouplist)
if
(
copy_from_user
(
groups
,
grouplist
,
gidsetsize
*
sizeof
(
old_gid_t
)))
return
-
EFAULT
;
for
(
i
=
0
;
i
<
gidsetsize
;
i
++
)
current
->
groups
[
i
]
=
(
gid_t
)
groups
[
i
];
new_groups
[
i
]
=
(
gid_t
)
groups
[
i
];
i
=
security_ops
->
task_setgroups
(
gidsetsize
,
new_groups
);
if
(
i
)
return
i
;
memcpy
(
current
->
groups
,
new_groups
,
gidsetsize
*
sizeof
(
gid_t
));
current
->
ngroups
=
gidsetsize
;
return
0
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment