Commit 1137c3f8 authored by Dmitry Safonov's avatar Dmitry Safonov Committed by Pavel Emelyanov

kerndat: add has_loginuid to kerndat_s

This value will differ on C/R:
  - on checkpoint it means that it's possible to dump logiuid values;
  - on restore it means that it's possible to unset loginuid and write
    saved value to unsetted loginuid.
Signed-off-by: 's avatarDmitry Safonov <dsafonov@odin.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 4a0351d7
......@@ -859,25 +859,6 @@ static int prepare_oom_score_adj(int value)
return ret;
}
static int prepare_loginuid(unsigned int value)
{
int fd, ret = 0;
char buf[11]; /* 4294967295 is maximum for u32 */
fd = open_proc_rw(PROC_SELF, "loginuid");
if (fd < 0)
return -1;
snprintf(buf, 11, "%u", value);
if (write(fd, buf, 11) < 0) {
pr_perror("Write %s to /proc/self/loginuid failed", buf);
ret = -1;
}
close(fd);
return ret;
}
static int prepare_proc_misc(pid_t pid, TaskCoreEntry *tc)
{
int ret;
......
......@@ -14,6 +14,7 @@ extern int kerndat_init(void);
extern int kerndat_init_rst(void);
extern int kerndat_get_dirty_track(void);
extern int kerndat_fdinfo_has_lock(void);
extern int kerndat_loginuid(bool only_dump);
struct kerndat_s {
dev_t shmem_dev;
......@@ -25,6 +26,7 @@ struct kerndat_s {
bool has_fdinfo_lock;
unsigned long task_size;
bool ipv6;
bool has_loginuid;
};
extern struct kerndat_s kdat;
......
......@@ -127,6 +127,7 @@ extern struct mount_info *parse_mountinfo(pid_t pid, struct ns_id *nsid, bool fo
extern int parse_pid_stat(pid_t pid, struct proc_pid_stat *s);
extern unsigned int parse_pid_loginuid(pid_t pid, int *err);
extern int parse_pid_oom_score_adj(pid_t pid, int *err);
extern int prepare_loginuid(unsigned int value);
extern int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list);
extern int parse_self_maps_lite(struct vm_area_list *vms);
extern int parse_pid_status(pid_t pid, struct proc_status_creds *);
......
......@@ -19,6 +19,7 @@
#include "cr_options.h"
#include "util.h"
#include "lsm.h"
#include "proc_parse.h"
struct kerndat_s kdat = {
/*
......@@ -419,6 +420,38 @@ static int get_ipv6()
return 0;
}
int kerndat_loginuid(bool only_dump)
{
unsigned int saved_loginuid;
int ret;
kdat.has_loginuid = false;
/* No such file, or perm fault: CONFIG_AUDITSYSCALL disabled */
saved_loginuid = parse_pid_loginuid(getpid(), &ret);
if (ret < 0)
return 0;
if (only_dump) {
kdat.has_loginuid = true;
return 0;
}
/*
* From kernel v3.13-rc2 it's possible to unset loginuid value,
* on that rely dump/restore code.
* See also: marc.info/?l=git-commits-head&m=138509506407067
*/
if (prepare_loginuid(INVALID_UID) < 0)
return 0;
/* Cleaning value back as it was */
if (prepare_loginuid(saved_loginuid) < 0)
return 0;
kdat.has_loginuid = true;
return 0;
}
int kerndat_init(void)
{
int ret;
......@@ -436,6 +469,8 @@ int kerndat_init(void)
ret = get_task_size();
if (!ret)
ret = get_ipv6();
if (!ret)
ret = kerndat_loginuid(true);
kerndat_lsm();
......@@ -461,6 +496,8 @@ int kerndat_init_rst(void)
ret = get_task_size();
if (!ret)
ret = get_ipv6();
if (!ret)
ret = kerndat_loginuid(false);
kerndat_lsm();
......
......@@ -809,6 +809,25 @@ err:
return -1;
}
int prepare_loginuid(unsigned int value)
{
int fd, ret = 0;
char buf[11]; /* 4294967295 is maximum for u32 */
fd = open_proc_rw(PROC_SELF, "loginuid");
if (fd < 0)
return -1;
snprintf(buf, 11, "%u", value);
if (write(fd, buf, 11) < 0) {
pr_perror("Write %s to /proc/self/loginuid failed", buf);
ret = -1;
}
close(fd);
return ret;
}
unsigned int parse_pid_loginuid(pid_t pid, int *err)
{
int fd;
......
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