Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
lxc
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
lxc
Commits
326bb02c
Unverified
Commit
326bb02c
authored
Jan 31, 2021
by
Stéphane Graber
Committed by
GitHub
Jan 31, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3641 from brauner/2021-01-30/fixes
attach: pidfd-based hardening and file-descriptor-only LSM interactions
parents
ee4aad1e
fbf281d3
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
201 additions
and
95 deletions
+201
-95
attach.c
src/lxc/attach.c
+103
-38
attach_options.h
src/lxc/attach_options.h
+1
-0
cgfsng.c
src/lxc/cgroups/cgfsng.c
+27
-27
apparmor.c
src/lxc/lsm/apparmor.c
+33
-28
lsm.h
src/lxc/lsm/lsm.h
+1
-0
nop.c
src/lxc/lsm/nop.c
+8
-2
selinux.c
src/lxc/lsm/selinux.c
+28
-0
No files found.
src/lxc/attach.c
View file @
326bb02c
This diff is collapsed.
Click to expand it.
src/lxc/attach_options.h
View file @
326bb02c
...
...
@@ -135,6 +135,7 @@ typedef struct lxc_attach_options_t {
/* .stdout_fd = */
1, \
/* .stderr_fd = */
2, \
/* .log_fd = */
-EBADF, \
/* .lsm_label = */
NULL, \
}
/*!
...
...
src/lxc/cgroups/cgfsng.c
View file @
326bb02c
...
...
@@ -3454,33 +3454,33 @@ struct cgroup_ops *cgfsng_ops_init(struct lxc_conf *conf)
if
(
cg_init
(
cgfsng_ops
,
conf
))
return
NULL
;
cgfsng_ops
->
data_init
=
cgfsng_data_init
;
cgfsng_ops
->
payload_destroy
=
cgfsng_payload_destroy
;
cgfsng_ops
->
monitor_destroy
=
cgfsng_monitor_destroy
;
cgfsng_ops
->
monitor_create
=
cgfsng_monitor_create
;
cgfsng_ops
->
monitor_enter
=
cgfsng_monitor_enter
;
cgfsng_ops
->
monitor_delegate_controllers
=
cgfsng_monitor_delegate_controllers
;
cgfsng_ops
->
payload_delegate_controllers
=
cgfsng_payload_delegate_controllers
;
cgfsng_ops
->
payload_create
=
cgfsng_payload_create
;
cgfsng_ops
->
payload_enter
=
cgfsng_payload_enter
;
cgfsng_ops
->
payload_finalize
=
cgfsng_payload_finalize
;
cgfsng_ops
->
escape
=
cgfsng_escape
;
cgfsng_ops
->
num_hierarchies
=
cgfsng_num_hierarchies
;
cgfsng_ops
->
get_hierarchies
=
cgfsng_get_hierarchies
;
cgfsng_ops
->
get_cgroup
=
cgfsng_get_cgroup
;
cgfsng_ops
->
get
=
cgfsng_get
;
cgfsng_ops
->
set
=
cgfsng_set
;
cgfsng_ops
->
freeze
=
cgfsng_freeze
;
cgfsng_ops
->
unfreeze
=
cgfsng_unfreeze
;
cgfsng_ops
->
setup_limits_legacy
=
cgfsng_setup_limits_legacy
;
cgfsng_ops
->
setup_limits
=
cgfsng_setup_limits
;
cgfsng_ops
->
driver
=
"cgfsng"
;
cgfsng_ops
->
version
=
"1.0.0"
;
cgfsng_ops
->
attach
=
cgfsng_attach
;
cgfsng_ops
->
chown
=
cgfsng_chown
;
cgfsng_ops
->
mount
=
cgfsng_mount
;
cgfsng_ops
->
devices_activate
=
cgfsng_devices_activate
;
cgfsng_ops
->
get_limiting_cgroup
=
cgfsng_get_limiting_cgroup
;
cgfsng_ops
->
data_init
=
cgfsng_data_init
;
cgfsng_ops
->
payload_destroy
=
cgfsng_payload_destroy
;
cgfsng_ops
->
monitor_destroy
=
cgfsng_monitor_destroy
;
cgfsng_ops
->
monitor_create
=
cgfsng_monitor_create
;
cgfsng_ops
->
monitor_enter
=
cgfsng_monitor_enter
;
cgfsng_ops
->
monitor_delegate_controllers
=
cgfsng_monitor_delegate_controllers
;
cgfsng_ops
->
payload_delegate_controllers
=
cgfsng_payload_delegate_controllers
;
cgfsng_ops
->
payload_create
=
cgfsng_payload_create
;
cgfsng_ops
->
payload_enter
=
cgfsng_payload_enter
;
cgfsng_ops
->
payload_finalize
=
cgfsng_payload_finalize
;
cgfsng_ops
->
escape
=
cgfsng_escape
;
cgfsng_ops
->
num_hierarchies
=
cgfsng_num_hierarchies
;
cgfsng_ops
->
get_hierarchies
=
cgfsng_get_hierarchies
;
cgfsng_ops
->
get_cgroup
=
cgfsng_get_cgroup
;
cgfsng_ops
->
get
=
cgfsng_get
;
cgfsng_ops
->
set
=
cgfsng_set
;
cgfsng_ops
->
freeze
=
cgfsng_freeze
;
cgfsng_ops
->
unfreeze
=
cgfsng_unfreeze
;
cgfsng_ops
->
setup_limits_legacy
=
cgfsng_setup_limits_legacy
;
cgfsng_ops
->
setup_limits
=
cgfsng_setup_limits
;
cgfsng_ops
->
driver
=
"cgfsng"
;
cgfsng_ops
->
version
=
"1.0.0"
;
cgfsng_ops
->
attach
=
cgfsng_attach
;
cgfsng_ops
->
chown
=
cgfsng_chown
;
cgfsng_ops
->
mount
=
cgfsng_mount
;
cgfsng_ops
->
devices_activate
=
cgfsng_devices_activate
;
cgfsng_ops
->
get_limiting_cgroup
=
cgfsng_get_limiting_cgroup
;
return
move_ptr
(
cgfsng_ops
);
}
src/lxc/lsm/apparmor.c
View file @
326bb02c
...
...
@@ -441,6 +441,22 @@ again:
return
buf
;
}
static
char
*
apparmor_process_label_get_at
(
struct
lsm_ops
*
ops
,
int
fd_pid
)
{
__do_free
char
*
label
=
NULL
;
size_t
len
;
label
=
read_file_at
(
fd_pid
,
"attr/current"
);
if
(
!
label
)
return
log_error_errno
(
NULL
,
errno
,
"Failed to get AppArmor context"
);
len
=
strcspn
(
label
,
"
\n
\t
"
);
if
(
len
)
label
[
len
]
=
'\0'
;
return
move_ptr
(
label
);
}
/*
* Probably makes sense to reorganize these to only read
* the label once
...
...
@@ -1180,45 +1196,33 @@ static int apparmor_process_label_set_at(struct lsm_ops *ops, int label_fd, cons
static
int
apparmor_process_label_set
(
struct
lsm_ops
*
ops
,
const
char
*
inlabel
,
struct
lxc_conf
*
conf
,
bool
on_exec
)
{
int
label_fd
,
ret
;
pid_t
tid
;
__do_close
int
label_fd
=
-
EBADF
;
int
ret
;
const
char
*
label
;
if
(
!
ops
->
aa_enabled
)
return
log_error
(
-
1
,
"AppArmor not enabled"
);
return
log_error
_errno
(
-
EOPNOTSUPP
,
EOPNOTSUPP
,
"AppArmor not enabled"
);
label
=
inlabel
?
inlabel
:
conf
->
lsm_aa_profile_computed
;
if
(
!
label
)
{
ERROR
(
"LSM wasn't prepared"
);
return
-
1
;
}
if
(
!
label
)
return
log_error_errno
(
-
EINVAL
,
EINVAL
,
"LSM wasn't prepared"
);
/* user may request that we just ignore apparmor */
if
(
strcmp
(
label
,
AA_UNCHANGED
)
==
0
)
{
INFO
(
"AppArmor profile unchanged per user request"
);
return
0
;
}
if
(
strcmp
(
label
,
AA_UNCHANGED
)
==
0
)
return
log_info
(
0
,
"AppArmor profile unchanged per user request"
);
if
(
strcmp
(
label
,
"unconfined"
)
==
0
&&
apparmor_am_unconfined
(
ops
))
{
INFO
(
"AppArmor profile unchanged"
);
return
0
;
}
tid
=
lxc_raw_gettid
();
label_fd
=
apparmor_process_label_fd_get
(
ops
,
tid
,
on_exec
);
if
(
label_fd
<
0
)
{
SYSERROR
(
"Failed to change AppArmor profile to %s"
,
label
);
return
-
1
;
}
if
(
strcmp
(
label
,
"unconfined"
)
==
0
&&
apparmor_am_unconfined
(
ops
))
return
log_info
(
0
,
"AppArmor profile unchanged"
);
label_fd
=
apparmor_process_label_fd_get
(
ops
,
lxc_raw_gettid
(),
on_exec
);
if
(
label_fd
<
0
)
return
log_error_errno
(
-
EINVAL
,
EINVAL
,
"Failed to change AppArmor profile to %s"
,
label
);
ret
=
apparmor_process_label_set_at
(
ops
,
label_fd
,
label
,
on_exec
);
close
(
label_fd
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to change AppArmor profile to %s"
,
label
);
return
-
1
;
}
if
(
ret
<
0
)
return
log_error_errno
(
-
EINVAL
,
EINVAL
,
"Failed to change AppArmor profile to %s"
,
label
);
INFO
(
"Changed AppArmor profile to %s"
,
label
);
return
0
;
return
log_info
(
0
,
"Changed AppArmor profile to %s"
,
label
);
}
static
struct
lsm_ops
apparmor_ops
=
{
...
...
@@ -1237,6 +1241,7 @@ static struct lsm_ops apparmor_ops = {
.
process_label_fd_get
=
apparmor_process_label_fd_get
,
.
process_label_get
=
apparmor_process_label_get
,
.
process_label_set
=
apparmor_process_label_set
,
.
process_label_get_at
=
apparmor_process_label_get_at
,
.
process_label_set_at
=
apparmor_process_label_set_at
,
};
...
...
src/lxc/lsm/lsm.h
View file @
326bb02c
...
...
@@ -30,6 +30,7 @@ struct lsm_ops {
int
(
*
prepare
)(
struct
lsm_ops
*
ops
,
struct
lxc_conf
*
conf
,
const
char
*
lxcpath
);
void
(
*
cleanup
)(
struct
lsm_ops
*
ops
,
struct
lxc_conf
*
conf
,
const
char
*
lxcpath
);
int
(
*
process_label_fd_get
)(
struct
lsm_ops
*
ops
,
pid_t
pid
,
bool
on_exec
);
char
*
(
*
process_label_get_at
)(
struct
lsm_ops
*
ops
,
int
fd_pid
);
int
(
*
process_label_set_at
)(
struct
lsm_ops
*
ops
,
int
label_fd
,
const
char
*
label
,
bool
on_exec
);
};
...
...
src/lxc/lsm/nop.c
View file @
326bb02c
...
...
@@ -13,6 +13,11 @@ static char *nop_process_label_get(struct lsm_ops *ops, pid_t pid)
return
NULL
;
}
static
char
*
nop_process_label_get_at
(
struct
lsm_ops
*
ops
,
int
fd_pid
)
{
return
NULL
;
}
static
int
nop_process_label_set
(
struct
lsm_ops
*
ops
,
const
char
*
label
,
struct
lxc_conf
*
conf
,
bool
on_exec
)
{
...
...
@@ -63,8 +68,9 @@ static struct lsm_ops nop_ops = {
.
prepare
=
nop_prepare
,
.
process_label_fd_get
=
nop_process_label_fd_get
,
.
process_label_get
=
nop_process_label_get
,
.
process_label_set
=
nop_process_label_set
,
.
process_label_set_at
=
nop_process_label_set_at
,
.
process_label_set
=
nop_process_label_set
,
.
process_label_get_at
=
nop_process_label_get_at
,
.
process_label_set_at
=
nop_process_label_set_at
,
};
struct
lsm_ops
*
lsm_nop_ops_init
(
void
)
...
...
src/lxc/lsm/selinux.c
View file @
326bb02c
...
...
@@ -15,6 +15,7 @@
#include "config.h"
#include "log.h"
#include "lsm.h"
#include "memory_utils.h"
#define DEFAULT_LABEL "unconfined_t"
...
...
@@ -41,6 +42,32 @@ static char *selinux_process_label_get(struct lsm_ops *ops, pid_t pid)
}
/*
* selinux_process_label_get_at: Get SELinux context of a process
*
* @fd_pid : file descriptor to /proc/<pid> of the process
*
* Returns the context of the given pid. The caller must free()
* the returned string.
*
* Note that this relies on /proc being available.
*/
static
char
*
selinux_process_label_get_at
(
struct
lsm_ops
*
ops
,
int
fd_pid
)
{
__do_free
char
*
label
=
NULL
;
size_t
len
;
label
=
read_file_at
(
fd_pid
,
"attr/current"
);
if
(
!
label
)
return
log_error_errno
(
NULL
,
errno
,
"Failed to get SELinux context"
);
len
=
strcspn
(
label
,
"
\n
\t
"
);
if
(
len
)
label
[
len
]
=
'\0'
;
return
move_ptr
(
label
);
}
/*
* selinux_process_label_set: Set SELinux context of a process
*
* @label : label string
...
...
@@ -154,6 +181,7 @@ static struct lsm_ops selinux_ops = {
.
process_label_fd_get
=
selinux_process_label_fd_get
,
.
process_label_get
=
selinux_process_label_get
,
.
process_label_set
=
selinux_process_label_set
,
.
process_label_get_at
=
selinux_process_label_get_at
,
.
process_label_set_at
=
selinux_process_label_set_at
,
};
...
...
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