]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/attach.c
2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2008
7 * Daniel Lezcano <dlezcano at fr.ibm.com>
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.
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.
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
31 #include <sys/param.h>
32 #include <sys/prctl.h>
33 #include <sys/mount.h>
34 #include <sys/syscall.h>
35 #include <linux/unistd.h>
37 #if !HAVE_DECL_PR_CAPBSET_DROP
38 #define PR_CAPBSET_DROP 24
41 #include "namespace.h"
48 lxc_log_define(lxc_attach
, lxc
);
50 int setns(int fd
, int nstype
)
56 return syscall(__NR_setns
, fd
, nstype
);
60 /* Define getline() if missing from the C library */
63 #include <../include/getline.h>
67 struct lxc_proc_context_info
*lxc_proc_get_context_info(pid_t pid
)
69 struct lxc_proc_context_info
*info
= calloc(1, sizeof(*info
));
71 char proc_fn
[MAXPATHLEN
];
73 size_t line_bufsz
= 0;
77 SYSERROR("Could not allocate memory.");
81 /* read capabilities */
82 snprintf(proc_fn
, MAXPATHLEN
, "/proc/%d/status", pid
);
84 proc_file
= fopen(proc_fn
, "r");
86 SYSERROR("Could not open %s", proc_fn
);
91 while (getline(&line
, &line_bufsz
, proc_file
) != -1) {
92 ret
= sscanf(line
, "CapBnd: %llx", &info
->capability_mask
);
93 if (ret
!= EOF
&& ret
> 0) {
102 SYSERROR("Could not read capability bounding set from %s", proc_fn
);
107 /* read personality */
108 snprintf(proc_fn
, MAXPATHLEN
, "/proc/%d/personality", pid
);
110 proc_file
= fopen(proc_fn
, "r");
112 SYSERROR("Could not open %s", proc_fn
);
116 ret
= fscanf(proc_file
, "%lx", &info
->personality
);
119 if (ret
== EOF
|| ret
== 0) {
120 SYSERROR("Could not read personality from %s", proc_fn
);
133 int lxc_attach_to_ns(pid_t pid
, int which
)
135 char path
[MAXPATHLEN
];
136 /* according to <http://article.gmane.org/gmane.linux.kernel.containers.lxc.devel/1429>,
137 * the file for user namepsaces in /proc/$pid/ns will be called
138 * 'user' once the kernel supports it
140 static char *ns
[] = { "mnt", "pid", "uts", "ipc", "user", "net" };
141 static int flags
[] = {
142 CLONE_NEWNS
, CLONE_NEWPID
, CLONE_NEWUTS
, CLONE_NEWIPC
,
143 CLONE_NEWUSER
, CLONE_NEWNET
145 static const int size
= sizeof(ns
) / sizeof(char *);
147 int i
, j
, saved_errno
;
150 snprintf(path
, MAXPATHLEN
, "/proc/%d/ns", pid
);
151 if (access(path
, X_OK
)) {
152 ERROR("Does this kernel version support 'attach' ?");
156 for (i
= 0; i
< size
; i
++) {
157 /* ignore if we are not supposed to attach to that
160 if (which
!= -1 && !(which
& flags
[i
])) {
165 snprintf(path
, MAXPATHLEN
, "/proc/%d/ns/%s", pid
, ns
[i
]);
166 fd
[i
] = open(path
, O_RDONLY
);
170 /* close all already opened file descriptors before
171 * we return an error, so we don't leak them
173 for (j
= 0; j
< i
; j
++)
177 SYSERROR("failed to open '%s'", path
);
182 for (i
= 0; i
< size
; i
++) {
183 if (fd
[i
] >= 0 && setns(fd
[i
], 0) != 0) {
186 for (j
= i
; j
< size
; j
++)
190 SYSERROR("failed to set namespace '%s'", ns
[i
]);
200 int lxc_attach_remount_sys_proc()
204 ret
= unshare(CLONE_NEWNS
);
206 SYSERROR("failed to unshare mount namespace");
210 /* assume /proc is always mounted, so remount it */
211 ret
= umount2("/proc", MNT_DETACH
);
213 SYSERROR("failed to unmount /proc");
217 ret
= mount("none", "/proc", "proc", 0, NULL
);
219 SYSERROR("failed to remount /proc");
223 /* try to umount /sys - if it's not a mount point,
224 * we'll get EINVAL, then we ignore it because it
225 * may not have been mounted in the first place
227 ret
= umount2("/sys", MNT_DETACH
);
228 if (ret
< 0 && errno
!= EINVAL
) {
229 SYSERROR("failed to unmount /sys");
231 } else if (ret
== 0) {
233 ret
= mount("none", "/sys", "sysfs", 0, NULL
);
235 SYSERROR("failed to remount /sys");
243 int lxc_attach_drop_privs(struct lxc_proc_context_info
*ctx
)
245 int last_cap
= lxc_caps_last_cap();
248 for (cap
= 0; cap
<= last_cap
; cap
++) {
249 if (ctx
->capability_mask
& (1LL << cap
))
252 if (prctl(PR_CAPBSET_DROP
, cap
, 0, 0, 0)) {
253 SYSERROR("failed to remove capability id %d", cap
);