Commit 6c22bfe2 authored by Pavel Emelyanov's avatar Pavel Emelyanov

criu: Remove security

We no longer support root-mode service and suid binaries, so
any artificial restrictions no longer make sense.
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
Looks-good-to-me: Andrew Vagin <avagin@virtuozzo.com>
parent 35cb5996
...@@ -3,7 +3,6 @@ obj-y += mem.o ...@@ -3,7 +3,6 @@ obj-y += mem.o
obj-y += rst-malloc.o obj-y += rst-malloc.o
obj-y += cr-restore.o obj-y += cr-restore.o
obj-y += crtools.o obj-y += crtools.o
obj-y += security.o
obj-y += image.o obj-y += image.o
obj-y += image-desc.o obj-y += image-desc.o
obj-y += net.o obj-y += net.o
......
...@@ -77,7 +77,6 @@ ...@@ -77,7 +77,6 @@
#include "sysfs_parse.h" #include "sysfs_parse.h"
#include "action-scripts.h" #include "action-scripts.h"
#include "aio.h" #include "aio.h"
#include "security.h"
#include "lsm.h" #include "lsm.h"
#include "seccomp.h" #include "seccomp.h"
#include "seize.h" #include "seize.h"
......
...@@ -73,7 +73,6 @@ ...@@ -73,7 +73,6 @@
#include "file-lock.h" #include "file-lock.h"
#include "action-scripts.h" #include "action-scripts.h"
#include "aio.h" #include "aio.h"
#include "security.h"
#include "lsm.h" #include "lsm.h"
#include "seccomp.h" #include "seccomp.h"
#include "bitmap.h" #include "bitmap.h"
...@@ -2820,8 +2819,6 @@ rst_prep_creds_args(struct thread_creds_args *prev, CredsEntry *ce) ...@@ -2820,8 +2819,6 @@ rst_prep_creds_args(struct thread_creds_args *prev, CredsEntry *ce)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
if (!may_restore(ce))
return ERR_PTR(-EINVAL);
args = rst_mem_alloc(sizeof(*args), RM_PRIVATE); args = rst_mem_alloc(sizeof(*args), RM_PRIVATE);
if (!args) if (!args)
......
...@@ -27,10 +27,10 @@ ...@@ -27,10 +27,10 @@
#include "mount.h" #include "mount.h"
#include "cgroup.h" #include "cgroup.h"
#include "action-scripts.h" #include "action-scripts.h"
#include "security.h"
#include "sockets.h" #include "sockets.h"
#include "irmap.h" #include "irmap.h"
#include "kerndat.h" #include "kerndat.h"
#include "proc_parse.h"
#include "setproctitle.h" #include "setproctitle.h"
...@@ -233,9 +233,6 @@ static int setup_opts_from_req(int sk, CriuOpts *req) ...@@ -233,9 +233,6 @@ static int setup_opts_from_req(int sk, CriuOpts *req)
goto err; goto err;
} }
if (restrict_uid(ids.uid, ids.gid))
goto err;
if (fstat(sk, &st)) { if (fstat(sk, &st)) {
pr_perror("Can't get socket stat"); pr_perror("Can't get socket stat");
goto err; goto err;
......
...@@ -38,10 +38,10 @@ ...@@ -38,10 +38,10 @@
#include "cgroup.h" #include "cgroup.h"
#include "cpu.h" #include "cpu.h"
#include "action-scripts.h" #include "action-scripts.h"
#include "security.h"
#include "irmap.h" #include "irmap.h"
#include "fault-injection.h" #include "fault-injection.h"
#include "lsm.h" #include "lsm.h"
#include "proc_parse.h"
#include "setproctitle.h" #include "setproctitle.h"
...@@ -266,9 +266,6 @@ int main(int argc, char *argv[], char *envp[]) ...@@ -266,9 +266,6 @@ int main(int argc, char *argv[], char *envp[])
return 1; return 1;
cr_pb_init(); cr_pb_init();
if (restrict_uid(getuid(), getgid()))
return 1;
setproctitle_init(argc, argv, envp); setproctitle_init(argc, argv, envp);
if (argc < 2) if (argc < 2)
......
#ifndef __CR_SECURITY_H__
#define __CR_SECURITY_H__
#include "proc_parse.h"
#include "protobuf/creds.pb-c.h"
extern int restrict_uid(unsigned int uid, unsigned int gid);
extern bool may_dump(struct proc_status_creds *);
extern bool may_restore(struct _CredsEntry *);
extern bool cr_user_is_root(void);
extern int cr_fchown(int fd);
#endif /* __CR_SECURITY_H__ */
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include "util.h" #include "util.h"
#include "cr_options.h" #include "cr_options.h"
#include "servicefd.h" #include "servicefd.h"
#include "security.h"
#define DEFAULT_LOGFD STDERR_FILENO #define DEFAULT_LOGFD STDERR_FILENO
/* Enable timestamps if verbosity is increased from default */ /* Enable timestamps if verbosity is increased from default */
...@@ -86,12 +85,6 @@ int log_init(const char *output) ...@@ -86,12 +85,6 @@ int log_init(const char *output)
pr_perror("Can't create log file %s", output); pr_perror("Can't create log file %s", output);
return -1; return -1;
} }
if (cr_fchown(new_logfd)) {
pr_perror("Can't chown log file %s", output);
close(new_logfd);
return -1;
}
} else { } else {
new_logfd = dup(DEFAULT_LOGFD); new_logfd = dup(DEFAULT_LOGFD);
if (new_logfd < 0) { if (new_logfd < 0) {
...@@ -200,12 +193,6 @@ int write_pidfile(int pid) ...@@ -200,12 +193,6 @@ int write_pidfile(int pid)
return -1; return -1;
} }
if (cr_fchown(fd)) {
pr_perror("Can't chown pidfile %s", opts.pidfile);
close(fd);
return -1;
}
dprintf(fd, "%d", pid); dprintf(fd, "%d", pid);
close(fd); close(fd);
return 0; return 0;
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include "ptrace.h" #include "ptrace.h"
#include "proc_parse.h" #include "proc_parse.h"
#include "crtools.h" #include "crtools.h"
#include "security.h"
#include "seccomp.h" #include "seccomp.h"
int unseize_task(pid_t pid, int orig_st, int st) int unseize_task(pid_t pid, int orig_st, int st)
...@@ -188,11 +187,6 @@ try_again: ...@@ -188,11 +187,6 @@ try_again:
if (ret2) if (ret2)
goto err; goto err;
if (!may_dump(&cr)) {
pr_err("Check uid (pid: %d) failed\n", pid);
goto err;
}
if (ret < 0 || WIFEXITED(status) || WIFSIGNALED(status)) { if (ret < 0 || WIFEXITED(status) || WIFSIGNALED(status)) {
if (cr.state != 'Z') { if (cr.state != 'Z') {
if (pid == getpid()) if (pid == getpid())
......
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include "crtools.h"
#include "proc_parse.h"
#include "log.h"
#include "xmalloc.h"
#include "bug.h"
#include "protobuf/creds.pb-c.h"
/*
* UID, GID and groups of user requesting for C/R
*/
static unsigned int cr_uid, cr_gid;
static unsigned int cr_ngroups, *cr_groups;
/*
* Setup what user is requesting for dump (via rpc or using
* suid bit on crtools). Later we would deny to dump/restore
* a task, to which the original user doesn't have the direct
* access to. (Or implement some trickier security policy).
*/
int restrict_uid(unsigned int uid, unsigned int gid)
{
struct passwd *pwd;
unsigned int buf[NGROUPS_MAX];
int nbuf;
pr_info("Restrict C/R with %u:%u uid:gid\n", uid, gid);
cr_uid = uid;
cr_gid = gid;
/* skip obtaining additional groups for root, as they don't matter */
if (cr_uid == 0 && cr_gid == 0)
return 0;
pwd = getpwuid(uid);
if (!pwd) {
pr_perror("Can't get password file entry");
return -1;
}
nbuf = NGROUPS_MAX;
if (getgrouplist(pwd->pw_name, pwd->pw_gid, buf, &nbuf) < 0) {
pr_perror("Can't get group list");
return -1;
}
cr_ngroups = nbuf;
cr_groups = xmalloc(cr_ngroups*sizeof(*cr_groups));
if (!cr_groups)
return -1;
memcpy(cr_groups, buf, cr_ngroups*sizeof(*cr_groups));
return 0;
}
static bool check_uids(unsigned int rid, unsigned int eid, unsigned int sid)
{
if (cr_uid == 0)
return true;
if (cr_uid == rid && cr_uid == eid && cr_uid == sid)
return true;
pr_err("UID mismatch %u != (%u,%u,%u)\n", cr_uid, rid, eid, sid);
return false;
}
static bool contains(unsigned int *crgids, unsigned int crgids_num, unsigned int gid)
{
int i;
for (i = 0; i < crgids_num; ++i) {
if (crgids[i] == gid)
return true;
}
return false;
}
static bool check_gids(unsigned int rid, unsigned int eid, unsigned int sid)
{
if (cr_gid == 0)
return true;
if ((contains(cr_groups, cr_ngroups, rid) || cr_gid == rid) &&
(contains(cr_groups, cr_ngroups, eid) || cr_gid == eid) &&
(contains(cr_groups, cr_ngroups, sid) || cr_gid == sid))
return true;
pr_err("GID mismatch. User is absent in (%u,%u,%u)\n", rid, eid, sid);
return false;
}
/*
* There is no need to check groups on dump, because if uids and gids match
* then groups will match too. Btw, getting groups on dump is problematic.
* We can't parse proc, as it contains only first 32 groups. And we can't use
* getgrouplist, as it reads /etc/group which depends on the namespace.
*
* On restore we're getting groups from imgs and can check if user didn't add
* wrong groups by modifying images.
*/
static bool check_groups(unsigned int *groups, unsigned int ngroups)
{
int i;
if (cr_gid == 0)
return true;
for (i = 0; i < ngroups; ++i) {
if (!contains(cr_groups, cr_ngroups, groups[i])) {
pr_err("GID mismatch. User is absent in %u group\n",
groups[i]);
return false;
}
}
return true;
}
static bool check_caps(u32 *inh, u32 *eff, u32 *prm)
{
int i;
/*
* Impose the most strict requirements for now.
* "Real" root user can use any caps, other users may
* use none. Later we will implement more sophisticated
* security model.
*/
if (cr_uid == 0 && cr_gid == 0)
return true;
for (i = 0; i < CR_CAP_SIZE; i++) {
if (inh[i] != 0 || eff[i] != 0 || prm[i] != 0) {
pr_err("CAPs not allowed for non-root user\n");
return false;
}
}
return true;
}
bool cr_user_is_root()
{
return cr_uid == 0 && cr_gid == 0;
}
bool may_dump(struct proc_status_creds *creds)
{
return check_uids(creds->uids[0], creds->uids[1], creds->uids[2]) &&
check_gids(creds->gids[0], creds->gids[1], creds->gids[2]) &&
check_caps(creds->cap_inh, creds->cap_eff, creds->cap_prm);
}
bool may_restore(CredsEntry *creds)
{
return check_uids(creds->uid, creds->euid, creds->suid) &&
check_gids(creds->gid, creds->egid, creds->sgid) &&
check_groups(creds->groups, creds->n_groups) &&
check_caps(creds->cap_inh, creds->cap_eff, creds->cap_prm);
}
int cr_fchown(int fd)
{
if (cr_user_is_root())
return 0;
if (fchown(fd, cr_uid, cr_gid)) {
pr_perror("Can't chown to (%u,%u)", cr_uid, cr_gid);
return -1;
}
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment