int btrfs_list_get_path_rootid(int fd, u64 *treeid) { int ret; struct btrfs_ioctl_ino_lookup_args args; memset(&args, 0, sizeof(args)); args.objectid = BTRFS_FIRST_FREE_OBJECTID; ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args); if (ret < 0) { SYSWARN("Can't perform the search"); return ret; } *treeid = args.treeid; return 0; }
/** * Set close-on-exec flag to all fd`s except 0, 1, 2 * (stdin, stdout, stderr) */ void setup_inherited_fds() { struct dirent dirent, *direntp; int fd, fddir; DIR *dir; dir = opendir("/proc/self/fd"); if (!dir) { SYSWARN("failed to open dir /proc/self/fd/"); WARN("can`t check for inherited fds"); return; //Not a critical error } fddir = dirfd(dir); while (!readdir_r(dir, &dirent, &direntp)) { char procpath[64]; char path[PATH_MAX]; if (!direntp) break; if (!strcmp(direntp->d_name, ".")) continue; if (!strcmp(direntp->d_name, "..")) continue; fd = atoi(direntp->d_name); if (fd == 0 || fd == 1 || fd == 2 || fd == fddir) continue; /* found inherited fd, setting FD_CLOEXEC */ if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { SYSERROR("can`t close-on-exec on fd %d", fd); throw -1; } } if (closedir(dir)) { SYSERROR("failed to close directory"); throw -1; } }
/* * lxc_cmd_rsp_send: Send a command response * * @fd : file descriptor of socket to send response on * @rsp : response to send * * Returns 0 on success, < 0 on failure */ static int lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp) { ssize_t ret; errno = EMSGSIZE; ret = lxc_send_nointr(fd, rsp, sizeof(*rsp), MSG_NOSIGNAL); if (ret < 0 || (size_t)ret != sizeof(*rsp)) { SYSERROR("Failed to send command response %zd", ret); return -1; } if (!rsp->data || rsp->datalen <= 0) return 0; errno = EMSGSIZE; ret = lxc_send_nointr(fd, rsp->data, rsp->datalen, MSG_NOSIGNAL); if (ret < 0 || ret != (ssize_t)rsp->datalen) { SYSWARN("Failed to send command response data %zd", ret); return -1; } return 0; }
int storage_destroy_wrapper(void *data) { struct lxc_conf *conf = data; if (setgid(0) < 0) { SYSERROR("Failed to setgid to 0"); return -1; } if (setgroups(0, NULL) < 0) SYSWARN("Failed to clear groups"); if (setuid(0) < 0) { SYSERROR("Failed to setuid to 0"); return -1; } if (!storage_destroy(conf)) { ERROR("Failed to destroy storage"); return -1; } return 0; }
/* * lxc_cmd_rsp_recv: Receive a response to a command * * @sock : the socket connected to the container * @cmd : command to put response in * * Returns the size of the response message or < 0 on failure * * Note that if the command response datalen > 0, then data is * a malloc()ed buffer and should be free()ed by the caller. If * the response data is <= a void * worth of data, it will be * stored directly in data and datalen will be 0. * * As a special case, the response for LXC_CMD_CONSOLE is created * here as it contains an fd for the master pty passed through the * unix socket. */ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd) { int ret, rspfd; struct lxc_cmd_rsp *rsp = &cmd->rsp; ret = lxc_abstract_unix_recv_fds(sock, &rspfd, 1, rsp, sizeof(*rsp)); if (ret < 0) { SYSWARN("Failed to receive response for command \"%s\"", lxc_cmd_str(cmd->req.cmd)); if (errno == ECONNRESET) return -1; return -1; } TRACE("Command \"%s\" received response", lxc_cmd_str(cmd->req.cmd)); if (cmd->req.cmd == LXC_CMD_CONSOLE) { struct lxc_cmd_console_rsp_data *rspdata; /* recv() returns 0 bytes when a tty cannot be allocated, * rsp->ret is < 0 when the peer permission check failed */ if (ret == 0 || rsp->ret < 0) return 0; rspdata = malloc(sizeof(*rspdata)); if (!rspdata) { errno = ENOMEM; ERROR("Failed to allocate response buffer for command \"%s\"", lxc_cmd_str(cmd->req.cmd)); return -1; } rspdata->masterfd = rspfd; rspdata->ttynum = PTR_TO_INT(rsp->data); rsp->data = rspdata; } if (rsp->datalen == 0) { DEBUG("Response data length for command \"%s\" is 0", lxc_cmd_str(cmd->req.cmd)); return ret; } if ((rsp->datalen > LXC_CMD_DATA_MAX) && (cmd->req.cmd != LXC_CMD_CONSOLE_LOG)) { ERROR("Response data for command \"%s\" is too long: %d bytes > %d", lxc_cmd_str(cmd->req.cmd), rsp->datalen, LXC_CMD_DATA_MAX); return -1; } if (cmd->req.cmd == LXC_CMD_CONSOLE_LOG) { rsp->data = malloc(rsp->datalen + 1); ((char *)rsp->data)[rsp->datalen] = '\0'; } else { rsp->data = malloc(rsp->datalen); } if (!rsp->data) { errno = ENOMEM; ERROR("Failed to allocate response buffer for command \"%s\"", lxc_cmd_str(cmd->req.cmd)); return -1; } ret = lxc_recv_nointr(sock, rsp->data, rsp->datalen, 0); if (ret != rsp->datalen) { SYSERROR("Failed to receive response data for command \"%s\"", lxc_cmd_str(cmd->req.cmd)); return -1; } return ret; }