1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
| #ifndef MNT_DETACH
#define MNT_DETACH 0x0000002
#endif
#ifndef MS_REC
#define MS_REC 0x4000
#endif
#ifndef MS_PRIVATE
#define MS_PRIVATE 1<<18 /* Private */
#endif
#define DIRNAMSZ 200
int handle_login(const char *user)
{
int ret = 0;
struct stat statbuf;
char dirnam[DIRNAMSZ], oldroot[DIRNAMSZ];
snprintf(dirnam, DIRNAMSZ, "/user/%s", user);
ret = stat(dirnam, &statbuf);
if (ret != 0 || !S_ISDIR(statbuf.st_mode))
return PAM_SUCCESS;
ret = unshare(CLONE_NEWNS);
if (ret) {
mysyslog(LOG_ERR, "failed to unshare mounts for %s, error %d\n",
user, errno);
return PAM_SESSION_ERR;
}
ret = chdir(dirnam);
if (ret) {
mysyslog(LOG_ERR, "failed to unshare mounts for %s, error %d\n",
user, errno);
return PAM_SESSION_ERR;
}
snprintf(oldroot, DIRNAMSZ, "%s/__my_private_mnt__", dirnam);
ret = pivot_root(dirnam, oldroot);
if (ret) {
mysyslog(LOG_ERR, "failed to pivot_root for %s, error %d\n",
user, errno);
mysyslog(LOG_ERR, "pivot_root was (%s,%s)\n", dirnam, oldroot);
return PAM_SESSION_ERR;
}
ret = mount("", "/__my_private_mnt__", "dontcare", MS_REC|MS_PRIVATE, "");
if (ret) {
mysyslog(LOG_ERR, "failed to mark /tmp private for %s, error %d\n",
user, errno);
return PAM_SESSION_ERR;
}
ret = umount2("/__my_private_mnt__", MNT_DETACH);
if (ret) {
mysyslog(LOG_ERR, "failed to umount old_root %s, error %d\n",
user, ret);
return PAM_SESSION_ERR;
}
return PAM_SUCCESS;
}
|