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) ...@@ -859,25 +859,6 @@ static int prepare_oom_score_adj(int value)
return ret; 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) static int prepare_proc_misc(pid_t pid, TaskCoreEntry *tc)
{ {
int ret; int ret;
......
...@@ -14,6 +14,7 @@ extern int kerndat_init(void); ...@@ -14,6 +14,7 @@ extern int kerndat_init(void);
extern int kerndat_init_rst(void); extern int kerndat_init_rst(void);
extern int kerndat_get_dirty_track(void); extern int kerndat_get_dirty_track(void);
extern int kerndat_fdinfo_has_lock(void); extern int kerndat_fdinfo_has_lock(void);
extern int kerndat_loginuid(bool only_dump);
struct kerndat_s { struct kerndat_s {
dev_t shmem_dev; dev_t shmem_dev;
...@@ -25,6 +26,7 @@ struct kerndat_s { ...@@ -25,6 +26,7 @@ struct kerndat_s {
bool has_fdinfo_lock; bool has_fdinfo_lock;
unsigned long task_size; unsigned long task_size;
bool ipv6; bool ipv6;
bool has_loginuid;
}; };
extern struct kerndat_s kdat; extern struct kerndat_s kdat;
......
...@@ -127,6 +127,7 @@ extern struct mount_info *parse_mountinfo(pid_t pid, struct ns_id *nsid, bool fo ...@@ -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 int parse_pid_stat(pid_t pid, struct proc_pid_stat *s);
extern unsigned int parse_pid_loginuid(pid_t pid, int *err); 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 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_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_self_maps_lite(struct vm_area_list *vms);
extern int parse_pid_status(pid_t pid, struct proc_status_creds *); extern int parse_pid_status(pid_t pid, struct proc_status_creds *);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "cr_options.h" #include "cr_options.h"
#include "util.h" #include "util.h"
#include "lsm.h" #include "lsm.h"
#include "proc_parse.h"
struct kerndat_s kdat = { struct kerndat_s kdat = {
/* /*
...@@ -419,6 +420,38 @@ static int get_ipv6() ...@@ -419,6 +420,38 @@ static int get_ipv6()
return 0; 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 kerndat_init(void)
{ {
int ret; int ret;
...@@ -436,6 +469,8 @@ int kerndat_init(void) ...@@ -436,6 +469,8 @@ int kerndat_init(void)
ret = get_task_size(); ret = get_task_size();
if (!ret) if (!ret)
ret = get_ipv6(); ret = get_ipv6();
if (!ret)
ret = kerndat_loginuid(true);
kerndat_lsm(); kerndat_lsm();
...@@ -461,6 +496,8 @@ int kerndat_init_rst(void) ...@@ -461,6 +496,8 @@ int kerndat_init_rst(void)
ret = get_task_size(); ret = get_task_size();
if (!ret) if (!ret)
ret = get_ipv6(); ret = get_ipv6();
if (!ret)
ret = kerndat_loginuid(false);
kerndat_lsm(); kerndat_lsm();
......
...@@ -809,6 +809,25 @@ err: ...@@ -809,6 +809,25 @@ err:
return -1; 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) unsigned int parse_pid_loginuid(pid_t pid, int *err)
{ {
int fd; 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