]>
Commit | Line | Data |
---|---|---|
e0732705 CS |
1 | /* |
2 | * lxc: linux Container library | |
3 | * | |
4 | * (C) Copyright IBM Corp. 2007, 2008 | |
5 | * | |
6 | * Authors: | |
7 | * Daniel Lezcano <dlezcano at fr.ibm.com> | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
22 | */ | |
23 | ||
24 | #define _GNU_SOURCE | |
25 | #include <unistd.h> | |
26 | #include <stdio.h> | |
27 | #include <string.h> | |
28 | #include <stdlib.h> | |
29 | #include <errno.h> | |
30 | #include <fcntl.h> | |
31 | #include <sys/param.h> | |
32 | #include <sys/prctl.h> | |
910bb4fa | 33 | #include <linux/unistd.h> |
e0732705 CS |
34 | |
35 | #if !HAVE_DECL_PR_CAPBSET_DROP | |
36 | #define PR_CAPBSET_DROP 24 | |
37 | #endif | |
38 | ||
39 | #include "namespace.h" | |
40 | #include "log.h" | |
41 | #include "attach.h" | |
42 | #include "caps.h" | |
43 | #include "cgroup.h" | |
44 | #include "config.h" | |
45 | ||
e0732705 CS |
46 | lxc_log_define(lxc_attach, lxc); |
47 | ||
48 | int setns(int fd, int nstype) | |
49 | { | |
50 | #ifndef __NR_setns | |
51 | errno = ENOSYS; | |
52 | return -1; | |
53 | #else | |
54 | return syscall(__NR_setns, fd, nstype); | |
55 | #endif | |
56 | } | |
57 | ||
58 | struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid) | |
59 | { | |
60 | struct lxc_proc_context_info *info = calloc(1, sizeof(*info)); | |
61 | FILE *proc_file; | |
62 | char proc_fn[MAXPATHLEN]; | |
460a1cf0 | 63 | char *line = NULL; |
e0732705 | 64 | size_t line_bufsz = 0; |
460a1cf0 | 65 | int ret, found; |
e0732705 CS |
66 | |
67 | if (!info) { | |
68 | SYSERROR("Could not allocate memory."); | |
69 | return NULL; | |
70 | } | |
71 | ||
72 | /* read capabilities */ | |
73 | snprintf(proc_fn, MAXPATHLEN, "/proc/%d/status", pid); | |
74 | ||
75 | proc_file = fopen(proc_fn, "r"); | |
76 | if (!proc_file) { | |
77 | SYSERROR("Could not open %s", proc_fn); | |
78 | goto out_error; | |
79 | } | |
80 | ||
81 | found = 0; | |
82 | while (getline(&line, &line_bufsz, proc_file) != -1) { | |
83 | ret = sscanf(line, "CapBnd: %llx", &info->capability_mask); | |
84 | if (ret != EOF && ret > 0) { | |
85 | found = 1; | |
86 | break; | |
87 | } | |
88 | } | |
89 | ||
90 | fclose(proc_file); | |
91 | ||
92 | if (!found) { | |
93 | SYSERROR("Could not read capability bounding set from %s", proc_fn); | |
94 | errno = ENOENT; | |
95 | goto out_error; | |
96 | } | |
97 | ||
98 | /* read personality */ | |
99 | snprintf(proc_fn, MAXPATHLEN, "/proc/%d/personality", pid); | |
100 | ||
101 | proc_file = fopen(proc_fn, "r"); | |
102 | if (!proc_file) { | |
103 | SYSERROR("Could not open %s", proc_fn); | |
104 | goto out_error; | |
105 | } | |
106 | ||
107 | ret = fscanf(proc_file, "%lx", &info->personality); | |
108 | fclose(proc_file); | |
109 | ||
110 | if (ret == EOF || ret == 0) { | |
111 | SYSERROR("Could not read personality from %s", proc_fn); | |
112 | errno = ENOENT; | |
113 | goto out_error; | |
114 | } | |
115 | ||
e0732705 CS |
116 | return info; |
117 | ||
118 | out_error: | |
460a1cf0 | 119 | free(info); |
e0732705 CS |
120 | free(line); |
121 | return NULL; | |
122 | } | |
123 | ||
99d50954 CS |
124 | int lxc_attach_to_ns(pid_t pid) |
125 | { | |
126 | char path[MAXPATHLEN]; | |
127 | char *ns[] = { "pid", "mnt", "net", "ipc", "uts" }; | |
128 | const int size = sizeof(ns) / sizeof(char *); | |
129 | int fd[size]; | |
130 | int i; | |
131 | ||
132 | snprintf(path, MAXPATHLEN, "/proc/%d/ns", pid); | |
133 | if (access(path, X_OK)) { | |
134 | ERROR("Does this kernel version support 'attach' ?"); | |
135 | return -1; | |
136 | } | |
137 | ||
138 | for (i = 0; i < size; i++) { | |
139 | snprintf(path, MAXPATHLEN, "/proc/%d/ns/%s", pid, ns[i]); | |
140 | fd[i] = open(path, O_RDONLY); | |
141 | if (fd[i] < 0) { | |
142 | SYSERROR("failed to open '%s'", path); | |
143 | return -1; | |
144 | } | |
145 | } | |
146 | ||
147 | for (i = 0; i < size; i++) { | |
148 | if (setns(fd[i], 0)) { | |
149 | SYSERROR("failed to set namespace '%s'", ns[i]); | |
150 | return -1; | |
151 | } | |
152 | ||
153 | close(fd[i]); | |
154 | } | |
155 | ||
156 | return 0; | |
157 | } | |
158 | ||
e0732705 CS |
159 | int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx) |
160 | { | |
161 | int last_cap = lxc_caps_last_cap(); | |
162 | int cap; | |
163 | ||
164 | for (cap = 0; cap <= last_cap; cap++) { | |
165 | if (ctx->capability_mask & (1LL << cap)) | |
166 | continue; | |
167 | ||
168 | if (prctl(PR_CAPBSET_DROP, cap, 0, 0, 0)) { | |
169 | SYSERROR("failed to remove capability id %d", cap); | |
170 | return -1; | |
171 | } | |
172 | } | |
173 | ||
174 | return 0; | |
175 | } |