2012-01-10 18:03:00 +04:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
2012-01-11 15:45:00 +04:00
|
|
|
#include <errno.h>
|
2012-01-10 18:03:00 +04:00
|
|
|
|
|
|
|
#include <linux/limits.h>
|
|
|
|
|
2012-01-11 15:45:00 +04:00
|
|
|
#include <sys/types.h>
|
2012-02-07 19:32:11 +04:00
|
|
|
#include <sys/prctl.h>
|
2012-01-11 15:45:00 +04:00
|
|
|
#include <sys/mman.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/un.h>
|
|
|
|
|
2012-01-10 18:03:00 +04:00
|
|
|
#include "crtools.h"
|
|
|
|
|
|
|
|
#include "files.h"
|
|
|
|
#include "image.h"
|
|
|
|
#include "list.h"
|
|
|
|
#include "util.h"
|
2012-02-01 13:00:49 +03:00
|
|
|
#include "util-net.h"
|
2012-01-10 18:03:00 +04:00
|
|
|
#include "lock.h"
|
2012-03-27 12:42:59 +04:00
|
|
|
#include "sockets.h"
|
2012-01-10 18:03:00 +04:00
|
|
|
|
2012-01-11 15:45:00 +04:00
|
|
|
static struct fdinfo_desc *fdinfo_descs;
|
|
|
|
static int nr_fdinfo_descs;
|
|
|
|
|
|
|
|
static struct fdinfo_list_entry *fdinfo_list;
|
|
|
|
static int nr_fdinfo_list;
|
|
|
|
|
2012-01-10 18:03:00 +04:00
|
|
|
static struct fmap_fd *fmap_fds;
|
|
|
|
|
2012-02-22 18:51:27 +04:00
|
|
|
int prepare_shared_fdinfo(void)
|
|
|
|
{
|
|
|
|
fdinfo_descs = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, 0, 0);
|
|
|
|
if (fdinfo_descs == MAP_FAILED) {
|
|
|
|
pr_perror("Can't map fdinfo_descs");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
fdinfo_list = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, 0, 0);
|
|
|
|
if (fdinfo_list == MAP_FAILED) {
|
|
|
|
pr_perror("Can't map fdinfo_list");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-03-27 12:42:20 +04:00
|
|
|
static struct fdinfo_desc *find_fd(struct fdinfo_entry *fe)
|
2012-01-11 15:45:00 +04:00
|
|
|
{
|
|
|
|
struct fdinfo_desc *fi;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < nr_fdinfo_descs; i++) {
|
|
|
|
fi = fdinfo_descs + i;
|
2012-03-27 12:42:20 +04:00
|
|
|
if ((fi->id == fe->id) && (fi->type == fe->type))
|
2012-01-11 15:45:00 +04:00
|
|
|
return fi;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int collect_fd(int pid, struct fdinfo_entry *e)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct fdinfo_list_entry *le = &fdinfo_list[nr_fdinfo_list];
|
2012-02-28 18:27:28 +04:00
|
|
|
struct fdinfo_desc *desc;
|
2012-01-11 15:45:00 +04:00
|
|
|
|
2012-03-25 13:48:22 +04:00
|
|
|
pr_info("Collect fdinfo pid=%d fd=%ld id=%16x\n",
|
2012-02-28 18:27:28 +04:00
|
|
|
pid, e->addr, e->id);
|
2012-01-11 15:45:00 +04:00
|
|
|
|
|
|
|
nr_fdinfo_list++;
|
2012-02-02 01:28:16 +04:00
|
|
|
if ((nr_fdinfo_list) * sizeof(struct fdinfo_list_entry) >= 4096) {
|
2012-03-01 18:52:42 +04:00
|
|
|
pr_err("OOM storing fdinfo_list_entries\n");
|
2012-01-16 23:10:41 +03:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-01-11 15:45:00 +04:00
|
|
|
le->pid = pid;
|
|
|
|
le->fd = e->addr;
|
2012-03-26 23:11:00 +04:00
|
|
|
|
|
|
|
futex_init(&le->real_pid);
|
2012-01-11 15:45:00 +04:00
|
|
|
|
|
|
|
for (i = 0; i < nr_fdinfo_descs; i++) {
|
|
|
|
desc = &fdinfo_descs[i];
|
2012-02-28 18:27:28 +04:00
|
|
|
|
2012-03-27 12:42:20 +04:00
|
|
|
if ((desc->id != e->id) || (desc->type != e->type))
|
2012-01-11 15:45:00 +04:00
|
|
|
continue;
|
|
|
|
|
|
|
|
list_add(&le->list, &desc->list);
|
|
|
|
|
|
|
|
if (fdinfo_descs[i].pid < pid)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
desc->pid = pid;
|
|
|
|
desc->addr = e->addr;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((nr_fdinfo_descs + 1) * sizeof(struct fdinfo_desc) >= 4096) {
|
2012-03-01 18:52:42 +04:00
|
|
|
pr_err("OOM storing fdinfo descriptions\n");
|
2012-01-11 15:45:00 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
desc = &fdinfo_descs[nr_fdinfo_descs];
|
2012-02-28 18:27:28 +04:00
|
|
|
memzero(desc, sizeof(*desc));
|
2012-01-11 15:45:00 +04:00
|
|
|
|
2012-02-28 18:27:28 +04:00
|
|
|
desc->id = e->id;
|
2012-03-27 12:42:20 +04:00
|
|
|
desc->type = e->type;
|
2012-02-28 18:27:28 +04:00
|
|
|
desc->addr = e->addr;
|
|
|
|
desc->pid = pid;
|
2012-01-11 15:45:00 +04:00
|
|
|
INIT_LIST_HEAD(&desc->list);
|
2012-02-28 18:27:28 +04:00
|
|
|
|
2012-01-11 15:45:00 +04:00
|
|
|
list_add(&le->list, &desc->list);
|
|
|
|
nr_fdinfo_descs++;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int prepare_fd_pid(int pid)
|
|
|
|
{
|
2012-02-07 15:49:04 +04:00
|
|
|
int fdinfo_fd, ret = 0;
|
2012-01-11 15:45:00 +04:00
|
|
|
u32 type = 0;
|
|
|
|
|
|
|
|
fdinfo_fd = open_image_ro(CR_FD_FDINFO, pid);
|
|
|
|
if (fdinfo_fd < 0) {
|
2012-01-22 20:26:51 +04:00
|
|
|
if (errno == ENOENT)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return -1;
|
2012-01-11 15:45:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
struct fdinfo_entry e;
|
|
|
|
|
2012-02-07 15:49:04 +04:00
|
|
|
ret = read_img_eof(fdinfo_fd, &e);
|
|
|
|
if (ret <= 0)
|
2012-01-11 15:45:00 +04:00
|
|
|
break;
|
2012-02-07 15:49:04 +04:00
|
|
|
|
2012-01-16 19:17:24 +04:00
|
|
|
if (fd_is_special(&e))
|
2012-01-11 15:45:00 +04:00
|
|
|
continue;
|
2012-01-16 19:17:24 +04:00
|
|
|
|
2012-02-07 15:49:04 +04:00
|
|
|
ret = collect_fd(pid, &e);
|
|
|
|
if (ret < 0)
|
|
|
|
break;
|
2012-01-11 15:45:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
close(fdinfo_fd);
|
2012-02-07 15:49:04 +04:00
|
|
|
return ret;
|
2012-01-11 15:45:00 +04:00
|
|
|
}
|
|
|
|
|
2012-03-27 12:10:11 +04:00
|
|
|
static int open_fe_fd(struct fdinfo_entry *fe)
|
2012-01-10 18:03:00 +04:00
|
|
|
{
|
2012-03-25 20:24:53 +04:00
|
|
|
struct reg_file_entry rfe;
|
2012-01-10 18:03:00 +04:00
|
|
|
char path[PATH_MAX];
|
|
|
|
int tmp;
|
|
|
|
|
2012-03-25 20:24:53 +04:00
|
|
|
/* FIXME This should be made in more optimal way */
|
|
|
|
|
|
|
|
tmp = open_image_ro(CR_FD_REG_FILES);
|
|
|
|
if (tmp < 0)
|
2012-01-10 18:03:00 +04:00
|
|
|
return -1;
|
|
|
|
|
2012-03-25 20:24:53 +04:00
|
|
|
while (1) {
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = read_img_eof(tmp, &rfe);
|
|
|
|
if (ret < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!ret) {
|
|
|
|
pr_err("Can't find file id %x\n", fe->id);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rfe.id == fe->id)
|
|
|
|
break;
|
|
|
|
|
|
|
|
lseek(tmp, rfe.len, SEEK_CUR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (read(tmp, path, rfe.len) != rfe.len) {
|
|
|
|
pr_perror("Error reading path");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
close(tmp);
|
|
|
|
path[rfe.len] = '\0';
|
|
|
|
|
|
|
|
tmp = open(path, rfe.flags);
|
2012-01-10 18:03:00 +04:00
|
|
|
if (tmp < 0) {
|
2012-01-31 15:13:05 +04:00
|
|
|
pr_perror("Can't open file %s", path);
|
2012-01-10 18:03:00 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-03-25 20:24:53 +04:00
|
|
|
lseek(tmp, rfe.pos, SEEK_SET);
|
2012-01-10 18:03:00 +04:00
|
|
|
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int restore_cwd(struct fdinfo_entry *fe, int fd)
|
|
|
|
{
|
2012-03-24 19:56:13 +04:00
|
|
|
int cfd;
|
2012-01-10 18:03:00 +04:00
|
|
|
|
2012-03-27 12:10:11 +04:00
|
|
|
cfd = open_fe_fd(fe);
|
2012-03-24 19:56:13 +04:00
|
|
|
if (cfd < 0)
|
|
|
|
return cfd;
|
2012-01-10 18:03:00 +04:00
|
|
|
|
2012-03-24 19:56:13 +04:00
|
|
|
if (fchdir(cfd)) {
|
|
|
|
pr_perror("Can't chdir");
|
2012-01-10 18:03:00 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-03-24 19:56:13 +04:00
|
|
|
close(cfd);
|
2012-01-10 18:03:00 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-03-24 13:22:37 +04:00
|
|
|
int self_exe_fd;
|
|
|
|
|
2012-02-07 19:32:11 +04:00
|
|
|
static int restore_exe_early(struct fdinfo_entry *fe, int fd)
|
|
|
|
{
|
2012-03-24 13:22:37 +04:00
|
|
|
int tmp;
|
|
|
|
|
2012-02-07 19:32:11 +04:00
|
|
|
/*
|
|
|
|
* We restore the EXE symlink at very late stage
|
|
|
|
* because of restrictions applied from kernel side,
|
2012-03-24 13:22:37 +04:00
|
|
|
* so keep this fd open till then.
|
2012-02-07 19:32:11 +04:00
|
|
|
*/
|
2012-03-24 13:22:37 +04:00
|
|
|
|
|
|
|
self_exe_fd = get_service_fd(SELF_EXE_FD_OFF);
|
|
|
|
if (self_exe_fd < 0)
|
|
|
|
return self_exe_fd;
|
|
|
|
|
2012-03-27 12:10:11 +04:00
|
|
|
tmp = open_fe_fd(fe);
|
2012-03-24 13:22:37 +04:00
|
|
|
if (tmp < 0)
|
|
|
|
return tmp;
|
|
|
|
|
|
|
|
return reopen_fd_as(self_exe_fd, tmp);
|
2012-02-07 19:32:11 +04:00
|
|
|
}
|
2012-01-11 15:45:00 +04:00
|
|
|
|
|
|
|
struct fdinfo_list_entry *find_fdinfo_list_entry(int pid, int fd, struct fdinfo_desc *fi)
|
2012-01-10 18:03:00 +04:00
|
|
|
{
|
2012-01-11 15:45:00 +04:00
|
|
|
struct fdinfo_list_entry *fle;
|
|
|
|
int found = 0;
|
|
|
|
|
|
|
|
list_for_each_entry(fle, &fi->list, list) {
|
|
|
|
if (fle->fd == fd && fle->pid == pid) {
|
|
|
|
found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BUG_ON(found == 0);
|
|
|
|
return fle;
|
|
|
|
}
|
|
|
|
|
2012-03-23 11:02:06 +03:00
|
|
|
static inline void transport_name_gen(struct sockaddr_un *addr, int *len,
|
|
|
|
int pid, long fd)
|
|
|
|
{
|
|
|
|
addr->sun_family = AF_UNIX;
|
|
|
|
snprintf(addr->sun_path, UNIX_PATH_MAX, "x/crtools-fd-%d-%ld", pid, fd);
|
|
|
|
*len = SUN_LEN(addr);
|
|
|
|
*addr->sun_path = '\0';
|
|
|
|
}
|
|
|
|
|
2012-01-11 15:45:00 +04:00
|
|
|
static int open_transport_fd(int pid, struct fdinfo_entry *fe,
|
2012-01-12 17:38:42 +03:00
|
|
|
struct fdinfo_desc *fi)
|
2012-01-11 15:45:00 +04:00
|
|
|
{
|
|
|
|
struct fdinfo_list_entry *fle;
|
|
|
|
struct sockaddr_un saddr;
|
|
|
|
int sock;
|
|
|
|
int ret, sun_len;
|
|
|
|
|
2012-01-16 19:35:35 +04:00
|
|
|
if (fi->pid == pid)
|
|
|
|
return 0;
|
|
|
|
|
2012-03-23 11:02:06 +03:00
|
|
|
transport_name_gen(&saddr, &sun_len, getpid(), fe->addr);
|
2012-01-11 15:45:00 +04:00
|
|
|
|
2012-04-02 21:58:34 +04:00
|
|
|
pr_info("\t%d: Create transport fd for %lx\n", pid, fe->addr);
|
2012-01-11 15:45:00 +04:00
|
|
|
|
|
|
|
fle = find_fdinfo_list_entry(pid, fe->addr, fi);
|
|
|
|
|
|
|
|
sock = socket(PF_UNIX, SOCK_DGRAM, 0);
|
|
|
|
if (sock < 0) {
|
|
|
|
pr_perror("Can't create socket");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
ret = bind(sock, &saddr, sun_len);
|
|
|
|
if (ret < 0) {
|
2012-01-31 15:13:05 +04:00
|
|
|
pr_perror("Can't bind unix socket %s", saddr.sun_path + 1);
|
2012-01-11 15:45:00 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2012-01-10 18:03:00 +04:00
|
|
|
|
2012-01-11 15:45:00 +04:00
|
|
|
ret = reopen_fd_as((int)fe->addr, sock);
|
|
|
|
if (ret < 0)
|
2012-01-10 18:03:00 +04:00
|
|
|
return -1;
|
|
|
|
|
2012-01-11 15:45:00 +04:00
|
|
|
pr_info("Wake up fdinfo pid=%d fd=%d\n", fle->pid, fle->fd);
|
2012-03-26 23:11:00 +04:00
|
|
|
futex_set_and_wake(&fle->real_pid, getpid());
|
2012-01-11 15:45:00 +04:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2012-01-10 18:03:00 +04:00
|
|
|
|
2012-01-11 15:45:00 +04:00
|
|
|
static int open_fd(int pid, struct fdinfo_entry *fe,
|
2012-01-12 17:38:42 +03:00
|
|
|
struct fdinfo_desc *fi, int fdinfo_fd)
|
2012-01-11 15:45:00 +04:00
|
|
|
{
|
|
|
|
int tmp;
|
|
|
|
int serv, sock;
|
|
|
|
struct sockaddr_un saddr;
|
|
|
|
struct fdinfo_list_entry *fle;
|
|
|
|
|
2012-01-16 19:35:35 +04:00
|
|
|
if ((fi->pid != pid) || (fe->addr != fi->addr))
|
|
|
|
return 0;
|
|
|
|
|
2012-03-27 12:42:59 +04:00
|
|
|
switch (fe->type) {
|
|
|
|
case FDINFO_REG:
|
|
|
|
tmp = open_fe_fd(fe);
|
|
|
|
break;
|
|
|
|
case FDINFO_INETSK:
|
|
|
|
tmp = open_inet_sk(fe);
|
|
|
|
break;
|
2012-03-29 21:47:00 +04:00
|
|
|
default:
|
|
|
|
tmp = -1;
|
|
|
|
break;
|
2012-03-27 12:42:59 +04:00
|
|
|
}
|
|
|
|
|
2012-01-10 18:03:00 +04:00
|
|
|
if (tmp < 0)
|
|
|
|
return -1;
|
|
|
|
|
2012-01-11 15:45:00 +04:00
|
|
|
if (reopen_fd_as((int)fe->addr, tmp))
|
|
|
|
return -1;
|
|
|
|
|
2012-04-02 21:58:34 +04:00
|
|
|
if (list_empty(&fi->list))
|
2012-01-11 15:45:00 +04:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
sock = socket(PF_UNIX, SOCK_DGRAM, 0);
|
|
|
|
if (sock < 0) {
|
|
|
|
pr_perror("Can't create socket");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-04-02 21:58:34 +04:00
|
|
|
pr_info("\t%d: Create fd for %lx\n", pid, fe->addr);
|
2012-01-11 15:45:00 +04:00
|
|
|
|
|
|
|
list_for_each_entry(fle, &fi->list, list) {
|
2012-02-01 13:00:49 +03:00
|
|
|
int len;
|
2012-01-11 15:45:00 +04:00
|
|
|
|
|
|
|
if (pid == fle->pid)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
pr_info("Wait fdinfo pid=%d fd=%d\n", fle->pid, fle->fd);
|
2012-03-26 23:11:00 +04:00
|
|
|
futex_wait_while(&fle->real_pid, 0);
|
2012-01-11 15:45:00 +04:00
|
|
|
|
2012-02-01 13:00:49 +03:00
|
|
|
pr_info("Send fd %d to %s\n", (int)fe->addr, saddr.sun_path + 1);
|
2012-03-26 23:11:00 +04:00
|
|
|
transport_name_gen(&saddr, &len, futex_get(&fle->real_pid), fle->fd);
|
2012-01-11 15:45:00 +04:00
|
|
|
|
2012-02-01 13:00:49 +03:00
|
|
|
if (send_fd(sock, &saddr, len, fe->addr) < 0) {
|
2012-01-11 15:45:00 +04:00
|
|
|
pr_perror("Can't send file descriptor");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
close(sock);
|
|
|
|
out:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-01-12 17:38:42 +03:00
|
|
|
static int receive_fd(int pid, struct fdinfo_entry *fe, struct fdinfo_desc *fi)
|
2012-01-11 15:45:00 +04:00
|
|
|
{
|
2012-01-16 19:18:31 +04:00
|
|
|
int tmp;
|
2012-01-11 15:45:00 +04:00
|
|
|
|
|
|
|
if (fi->pid == pid) {
|
2012-01-16 19:35:35 +04:00
|
|
|
if (fi->addr != fe->addr) {
|
|
|
|
tmp = dup2(fi->addr, fe->addr);
|
|
|
|
if (tmp < 0) {
|
2012-01-31 15:31:28 +04:00
|
|
|
pr_perror("Can't duplicate fd %ld %ld",
|
2012-01-16 19:35:35 +04:00
|
|
|
fi->addr, fe->addr);
|
|
|
|
return -1;
|
|
|
|
}
|
2012-01-11 15:45:00 +04:00
|
|
|
}
|
2012-01-16 19:35:35 +04:00
|
|
|
|
2012-01-11 15:45:00 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-04-02 21:58:34 +04:00
|
|
|
pr_info("\t%d: Receive fd for %lx\n", pid, fe->addr);
|
2012-01-11 15:45:00 +04:00
|
|
|
|
|
|
|
tmp = recv_fd(fe->addr);
|
|
|
|
if (tmp < 0) {
|
2012-02-01 13:00:49 +03:00
|
|
|
pr_err("Can't get fd %d\n", tmp);
|
2012-01-11 15:45:00 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
close(fe->addr);
|
|
|
|
|
2012-01-10 18:03:00 +04:00
|
|
|
return reopen_fd_as((int)fe->addr, tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int open_fmap(int pid, struct fdinfo_entry *fe, int fd)
|
|
|
|
{
|
|
|
|
struct fmap_fd *new;
|
2012-01-12 16:46:35 +04:00
|
|
|
int tmp;
|
2012-01-10 18:03:00 +04:00
|
|
|
|
2012-03-27 12:10:11 +04:00
|
|
|
tmp = open_fe_fd(fe);
|
2012-01-10 18:03:00 +04:00
|
|
|
if (tmp < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
pr_info("%d:\t\tWill map %lx to %d\n", pid, (unsigned long)fe->addr, tmp);
|
|
|
|
|
2012-01-12 16:46:35 +04:00
|
|
|
new = xmalloc(sizeof(*new));
|
|
|
|
if (!new) {
|
|
|
|
close_safe(&tmp);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-01-10 18:03:00 +04:00
|
|
|
new->start = fe->addr;
|
|
|
|
new->fd = tmp;
|
|
|
|
new->next = fmap_fds;
|
|
|
|
new->pid = pid;
|
|
|
|
|
|
|
|
fmap_fds = new;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-01-11 15:45:00 +04:00
|
|
|
static int open_fdinfo(int pid, struct fdinfo_entry *fe, int *fdinfo_fd, int state)
|
2012-01-10 18:03:00 +04:00
|
|
|
{
|
2012-01-11 15:45:00 +04:00
|
|
|
u32 mag;
|
2012-01-12 17:38:41 +03:00
|
|
|
int ret = 0;
|
2012-03-27 12:42:20 +04:00
|
|
|
struct fdinfo_desc *fi = find_fd(fe);
|
2012-01-10 18:03:00 +04:00
|
|
|
|
2012-01-11 15:45:00 +04:00
|
|
|
if (move_img_fd(fdinfo_fd, (int)fe->addr))
|
2012-01-10 18:03:00 +04:00
|
|
|
return -1;
|
|
|
|
|
2012-04-02 21:58:34 +04:00
|
|
|
pr_info("\t%d: Got fd for %lx\n", pid, fe->addr);
|
2012-01-10 18:03:00 +04:00
|
|
|
|
2012-03-27 12:42:59 +04:00
|
|
|
BUG_ON(fd_is_special(fe));
|
2012-01-10 18:03:00 +04:00
|
|
|
|
2012-01-16 19:35:35 +04:00
|
|
|
switch (state) {
|
|
|
|
case FD_STATE_PREP:
|
|
|
|
ret = open_transport_fd(pid, fe, fi);
|
|
|
|
break;
|
|
|
|
case FD_STATE_CREATE:
|
|
|
|
ret = open_fd(pid, fe, fi, *fdinfo_fd);
|
|
|
|
break;
|
|
|
|
case FD_STATE_RECV:
|
|
|
|
ret = receive_fd(pid, fe, fi);
|
|
|
|
break;
|
2012-01-11 15:45:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-01-16 19:18:05 +04:00
|
|
|
static int open_special_fdinfo(int pid, struct fdinfo_entry *fe,
|
|
|
|
int fdinfo_fd, int state)
|
|
|
|
{
|
2012-03-25 20:24:53 +04:00
|
|
|
if (state != FD_STATE_RECV)
|
2012-01-16 19:18:05 +04:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (fe->type == FDINFO_MAP)
|
|
|
|
return open_fmap(pid, fe, fdinfo_fd);
|
2012-03-06 15:52:00 +04:00
|
|
|
if (fe->type == FDINFO_CWD)
|
2012-01-16 19:18:05 +04:00
|
|
|
return restore_cwd(fe, fdinfo_fd);
|
2012-03-06 15:52:00 +04:00
|
|
|
if (fe->type == FDINFO_EXE)
|
2012-02-07 19:32:11 +04:00
|
|
|
return restore_exe_early(fe, fdinfo_fd);
|
2012-01-16 19:18:05 +04:00
|
|
|
|
2012-03-06 15:52:00 +04:00
|
|
|
pr_info("%d: fe->type: %d\n", pid, fe->type);
|
2012-01-16 19:18:05 +04:00
|
|
|
BUG_ON(1);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-01-11 15:45:00 +04:00
|
|
|
int prepare_fds(int pid)
|
|
|
|
{
|
2012-03-23 11:15:58 +03:00
|
|
|
u32 type = 0, ret;
|
2012-01-11 15:45:00 +04:00
|
|
|
int fdinfo_fd;
|
|
|
|
int state;
|
2012-01-10 20:02:00 +04:00
|
|
|
off_t offset, magic_offset;
|
2012-01-11 15:45:00 +04:00
|
|
|
|
|
|
|
struct fdinfo_entry fe;
|
|
|
|
int nr = 0;
|
|
|
|
|
|
|
|
pr_info("%d: Opening fdinfo-s\n", pid);
|
|
|
|
|
2012-01-10 20:02:00 +04:00
|
|
|
fdinfo_fd = open_image_ro(CR_FD_FDINFO, pid);
|
|
|
|
if (fdinfo_fd < 0) {
|
2012-01-31 15:13:05 +04:00
|
|
|
pr_perror("%d: Can't open pipes img", pid);
|
2012-01-10 20:02:00 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
magic_offset = lseek(fdinfo_fd, 0, SEEK_CUR);
|
|
|
|
|
2012-01-11 15:45:00 +04:00
|
|
|
for (state = 0; state < FD_STATE_MAX; state++) {
|
2012-01-10 20:02:00 +04:00
|
|
|
lseek(fdinfo_fd, magic_offset, SEEK_SET);
|
2012-01-10 18:03:00 +04:00
|
|
|
|
2012-01-11 15:45:00 +04:00
|
|
|
while (1) {
|
2012-03-23 11:15:58 +03:00
|
|
|
ret = read_img_eof(fdinfo_fd, &fe);
|
|
|
|
if (ret <= 0)
|
2012-01-11 15:45:00 +04:00
|
|
|
break;
|
|
|
|
|
2012-03-23 11:15:58 +03:00
|
|
|
if (fd_is_special(&fe))
|
|
|
|
ret = open_special_fdinfo(pid, &fe,
|
|
|
|
fdinfo_fd, state);
|
2012-03-25 20:24:53 +04:00
|
|
|
else
|
2012-03-23 11:15:58 +03:00
|
|
|
ret = open_fdinfo(pid, &fe, &fdinfo_fd, state);
|
2012-01-11 15:45:00 +04:00
|
|
|
|
2012-03-23 11:15:58 +03:00
|
|
|
if (ret)
|
|
|
|
break;
|
2012-01-10 18:03:00 +04:00
|
|
|
}
|
2012-03-23 11:15:58 +03:00
|
|
|
|
|
|
|
if (ret)
|
|
|
|
break;
|
2012-01-10 18:03:00 +04:00
|
|
|
}
|
2012-03-23 11:15:58 +03:00
|
|
|
|
2012-01-11 15:45:00 +04:00
|
|
|
close(fdinfo_fd);
|
2012-03-23 11:15:58 +03:00
|
|
|
return ret;
|
2012-01-10 18:03:00 +04:00
|
|
|
}
|
|
|
|
|
2012-02-22 16:53:22 +04:00
|
|
|
static struct fmap_fd *pull_fmap_fd(int pid, unsigned long start)
|
2012-01-10 18:03:00 +04:00
|
|
|
{
|
|
|
|
struct fmap_fd **p, *r;
|
|
|
|
|
|
|
|
pr_info("%d: Looking for %lx : ", pid, start);
|
|
|
|
|
|
|
|
for (p = &fmap_fds; *p != NULL; p = &(*p)->next) {
|
|
|
|
if ((*p)->start != start || (*p)->pid != pid)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
r = *p;
|
|
|
|
*p = r->next;
|
|
|
|
pr_info("found\n");
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
pr_info("not found\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-03-21 19:38:00 +04:00
|
|
|
int get_filemap_fd(int pid, struct vma_entry *vma_entry)
|
2012-01-10 18:03:00 +04:00
|
|
|
{
|
2012-03-21 19:38:00 +04:00
|
|
|
struct fmap_fd *fmap_fd;
|
|
|
|
|
|
|
|
fmap_fd = pull_fmap_fd(pid, vma_entry->start);
|
|
|
|
return fmap_fd ? fmap_fd->fd : -1;
|
2012-01-10 18:03:00 +04:00
|
|
|
}
|