489b61af8e1b744c5aac3117fb5b85a0b05cb732
[lttng-tools.git] / lttng-sessiond / utils.c
1 /*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 * Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; only version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #define _GNU_SOURCE
20 #include <errno.h>
21 #include <limits.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/wait.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29
30 #include <lttngerr.h>
31
32 #include "utils.h"
33
34 /*
35 * Write to writable pipe used to notify a thread.
36 */
37 int notify_thread_pipe(int wpipe)
38 {
39 int ret;
40
41 ret = write(wpipe, "!", 1);
42 if (ret < 0) {
43 PERROR("write poll pipe");
44 }
45
46 return ret;
47 }
48
49 /*
50 * Return pointer to home directory path using the env variable HOME.
51 *
52 * No home, NULL is returned.
53 */
54 const char *get_home_dir(void)
55 {
56 return ((const char *) getenv("HOME"));
57 }
58
59 /*
60 * Create recursively directory using the FULL path.
61 */
62 static
63 int _mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid)
64 {
65 int ret;
66 char *p, tmp[PATH_MAX];
67 size_t len;
68 mode_t old_umask;
69
70 ret = snprintf(tmp, sizeof(tmp), "%s", path);
71 if (ret < 0) {
72 PERROR("snprintf mkdir");
73 goto error;
74 }
75
76 len = ret;
77 if (tmp[len - 1] == '/') {
78 tmp[len - 1] = 0;
79 }
80
81 old_umask = umask(0);
82 for (p = tmp + 1; *p; p++) {
83 if (*p == '/') {
84 *p = 0;
85 ret = mkdir(tmp, mode);
86 if (ret < 0) {
87 if (!(errno == EEXIST)) {
88 PERROR("mkdir recursive");
89 ret = -errno;
90 goto umask_error;
91 }
92 }
93 *p = '/';
94 }
95 }
96
97 ret = mkdir(tmp, mode);
98 if (ret < 0) {
99 if (!(errno == EEXIST)) {
100 PERROR("mkdir recursive last piece");
101 ret = -errno;
102 } else {
103 ret = 0;
104 }
105 }
106
107 umask_error:
108 umask(old_umask);
109 error:
110 return ret;
111 }
112
113 static
114 int run_as(int (*cmd)(const char *path, mode_t mode, uid_t uid, gid_t gid),
115 const char *path, mode_t mode, uid_t uid, gid_t gid)
116 {
117 int ret = 0;
118 pid_t pid;
119
120 /*
121 * If we are non-root, we can only deal with our own uid.
122 */
123 if (geteuid() != 0) {
124 if (uid != geteuid()) {
125 ERR("Client (%d)/Server (%d) UID mismatch (and sessiond is not root)",
126 uid, geteuid());
127 return -EPERM;
128 }
129 return (*cmd)(path, mode, uid, gid);
130 }
131
132 pid = fork();
133 if (pid > 0) {
134 int status;
135
136 /*
137 * Parent: wait for child to return, in which case the
138 * shared memory map will have been created.
139 */
140 pid = wait(&status);
141 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
142 ret = -1;
143 goto end;
144 }
145 goto end;
146 } else if (pid == 0) {
147 /* Child */
148 setegid(gid);
149 if (ret < 0) {
150 perror("setegid");
151 exit(EXIT_FAILURE);
152 }
153 ret = seteuid(uid);
154 if (ret < 0) {
155 perror("seteuid");
156 exit(EXIT_FAILURE);
157 }
158 ret = (*cmd)(path, mode, uid, gid);
159 if (!ret)
160 exit(EXIT_SUCCESS);
161 else
162 exit(EXIT_FAILURE);
163 } else {
164 return -1;
165 }
166 end:
167 return ret;
168 }
169
170 int mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid)
171 {
172 DBG3("mkdir() recursive %s with mode %d for uid %d and gid %d",
173 path, mode, uid, gid);
174 return run_as(_mkdir_recursive, path, mode, uid, gid);
175 }
This page took 0.031525 seconds and 3 git commands to generate.