Fix: handle negative clock offset for lttng-ust metadata
[lttng-tools.git] / src / bin / lttng-sessiond / session.c
CommitLineData
5b74c7b1
DG
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 *
d14d33bf
AM
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2 only,
6 * as published by the Free Software Foundation.
91d76f53 7 *
5b74c7b1
DG
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
d14d33bf 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5b74c7b1
DG
11 * GNU General Public License for more details.
12 *
d14d33bf
AM
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
5b74c7b1
DG
16 */
17
6c1c0768 18#define _LGPL_SOURCE
6c9cc2ab 19#include <limits.h>
d022620a 20#include <inttypes.h>
5b74c7b1
DG
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
a304c14c 24#include <sys/stat.h>
f6a9efaa 25#include <urcu.h>
3d071855
MD
26#include <dirent.h>
27#include <sys/types.h>
5b74c7b1 28
990570ed 29#include <common/common.h>
db758600 30#include <common/sessiond-comm/sessiond-comm.h>
1e307fab 31
5b74c7b1
DG
32#include "session.h"
33
8c0faa1d 34/*
b5541356 35 * NOTES:
8c0faa1d 36 *
b5541356
DG
37 * No ltt_session.lock is taken here because those data structure are widely
38 * spread across the lttng-tools code base so before caling functions below
39 * that can read/write a session, the caller MUST acquire the session lock
54d01ffb 40 * using session_lock() and session_unlock().
8c0faa1d 41 */
8c0faa1d 42
5b74c7b1 43/*
b5541356 44 * Init tracing session list.
5b74c7b1 45 *
b5541356 46 * Please see session.h for more explanation and correct usage of the list.
5b74c7b1 47 */
b5541356
DG
48static struct ltt_session_list ltt_session_list = {
49 .head = CDS_LIST_HEAD_INIT(ltt_session_list.head),
50 .lock = PTHREAD_MUTEX_INITIALIZER,
a24f7994 51 .next_uuid = 0,
b5541356 52};
5b74c7b1 53
1c1c3634
DG
54/* These characters are forbidden in a session name. Used by validate_name. */
55static const char *forbidden_name_chars = "/";
56
57/*
58 * Validate the session name for forbidden characters.
59 *
60 * Return 0 on success else -1 meaning a forbidden char. has been found.
61 */
62static int validate_name(const char *name)
63{
64 int ret;
65 char *tok, *tmp_name;
66
67 assert(name);
68
69 tmp_name = strdup(name);
70 if (!tmp_name) {
71 /* ENOMEM here. */
72 ret = -1;
73 goto error;
74 }
75
76 tok = strpbrk(tmp_name, forbidden_name_chars);
77 if (tok) {
78 DBG("Session name %s contains a forbidden character", name);
79 /* Forbidden character has been found. */
80 ret = -1;
81 goto error;
82 }
83 ret = 0;
84
85error:
86 free(tmp_name);
87 return ret;
88}
89
5b74c7b1 90/*
050349bb 91 * Add a ltt_session structure to the global list.
5b74c7b1 92 *
050349bb 93 * The caller MUST acquire the session list lock before.
44e96653 94 * Returns the unique identifier for the session.
5b74c7b1 95 */
d022620a 96static uint64_t add_session_list(struct ltt_session *ls)
5b74c7b1 97{
0525e9ae
DG
98 assert(ls);
99
5b74c7b1 100 cds_list_add(&ls->list, &ltt_session_list.head);
a24f7994 101 return ltt_session_list.next_uuid++;
5b74c7b1
DG
102}
103
104/*
050349bb 105 * Delete a ltt_session structure to the global list.
b5541356 106 *
050349bb 107 * The caller MUST acquire the session list lock before.
5b74c7b1
DG
108 */
109static void del_session_list(struct ltt_session *ls)
110{
0525e9ae
DG
111 assert(ls);
112
5b74c7b1 113 cds_list_del(&ls->list);
5b74c7b1
DG
114}
115
b5541356 116/*
050349bb 117 * Return a pointer to the session list.
b5541356 118 */
54d01ffb 119struct ltt_session_list *session_get_list(void)
b5541356
DG
120{
121 return &ltt_session_list;
122}
123
124/*
6c9cc2ab 125 * Acquire session list lock
b5541356 126 */
54d01ffb 127void session_lock_list(void)
b5541356 128{
6c9cc2ab 129 pthread_mutex_lock(&ltt_session_list.lock);
b5541356
DG
130}
131
132/*
6c9cc2ab 133 * Release session list lock
b5541356 134 */
54d01ffb 135void session_unlock_list(void)
b5541356 136{
6c9cc2ab 137 pthread_mutex_unlock(&ltt_session_list.lock);
b5541356
DG
138}
139
140/*
6c9cc2ab 141 * Acquire session lock
b5541356 142 */
54d01ffb 143void session_lock(struct ltt_session *session)
b5541356 144{
0525e9ae
DG
145 assert(session);
146
6c9cc2ab
DG
147 pthread_mutex_lock(&session->lock);
148}
b5541356 149
6c9cc2ab
DG
150/*
151 * Release session lock
152 */
54d01ffb 153void session_unlock(struct ltt_session *session)
6c9cc2ab 154{
0525e9ae
DG
155 assert(session);
156
6c9cc2ab 157 pthread_mutex_unlock(&session->lock);
b5541356
DG
158}
159
5b74c7b1 160/*
74babd95
DG
161 * Return a ltt_session structure ptr that matches name. If no session found,
162 * NULL is returned. This must be called with the session lock held using
163 * session_lock_list and session_unlock_list.
5b74c7b1 164 */
58a1a227 165struct ltt_session *session_find_by_name(const char *name)
5b74c7b1 166{
5b74c7b1
DG
167 struct ltt_session *iter;
168
0525e9ae
DG
169 assert(name);
170
5f822d0a
DG
171 DBG2("Trying to find session by name %s", name);
172
5b74c7b1 173 cds_list_for_each_entry(iter, &ltt_session_list.head, list) {
1b110e1b 174 if (strncmp(iter->name, name, NAME_MAX) == 0) {
74babd95 175 goto found;
5b74c7b1
DG
176 }
177 }
178
74babd95 179 iter = NULL;
5b74c7b1 180
74babd95 181found:
5b74c7b1
DG
182 return iter;
183}
184
185/*
050349bb 186 * Delete session from the session list and free the memory.
5b74c7b1 187 *
050349bb 188 * Return -1 if no session is found. On success, return 1;
36b588ed 189 * Should *NOT* be called with RCU read-side lock held.
5b74c7b1 190 */
271933a4 191int session_destroy(struct ltt_session *session)
5b74c7b1 192{
271933a4 193 /* Safety check */
0525e9ae 194 assert(session);
271933a4
DG
195
196 DBG("Destroying session %s", session->name);
197 del_session_list(session);
271933a4 198 pthread_mutex_destroy(&session->lock);
07424f16 199
6addfa37 200 consumer_output_put(session->consumer);
6dc3064a 201 snapshot_destroy(&session->snapshot);
271933a4 202 free(session);
5b74c7b1 203
f73fabfd 204 return LTTNG_OK;
5b74c7b1
DG
205}
206
207/*
050349bb 208 * Create a brand new session and add it to the session list.
5b74c7b1 209 */
dec56f6c 210int session_create(char *name, uid_t uid, gid_t gid)
5b74c7b1 211{
f3ed775e 212 int ret;
5b74c7b1 213 struct ltt_session *new_session;
e07ae692 214
5b74c7b1 215 /* Allocate session data structure */
ba7f0ae5 216 new_session = zmalloc(sizeof(struct ltt_session));
5b74c7b1 217 if (new_session == NULL) {
df0f840b 218 PERROR("zmalloc");
f73fabfd 219 ret = LTTNG_ERR_FATAL;
f3ed775e 220 goto error_malloc;
5b74c7b1
DG
221 }
222
f3ed775e 223 /* Define session name */
5b74c7b1 224 if (name != NULL) {
74babd95 225 if (snprintf(new_session->name, NAME_MAX, "%s", name) < 0) {
f73fabfd 226 ret = LTTNG_ERR_FATAL;
f3ed775e 227 goto error_asprintf;
5b74c7b1
DG
228 }
229 } else {
f3ed775e 230 ERR("No session name given");
f73fabfd 231 ret = LTTNG_ERR_FATAL;
f3ed775e
DG
232 goto error;
233 }
234
1c1c3634
DG
235 ret = validate_name(name);
236 if (ret < 0) {
237 ret = LTTNG_ERR_SESSION_INVALID_CHAR;
238 goto error;
239 }
240
d3e2ba59 241 ret = gethostname(new_session->hostname, sizeof(new_session->hostname));
73184835
DG
242 if (ret < 0) {
243 if (errno == ENAMETOOLONG) {
244 new_session->hostname[sizeof(new_session->hostname) - 1] = '\0';
245 } else {
246 ret = LTTNG_ERR_FATAL;
247 goto error;
248 }
d3e2ba59
JD
249 }
250
1d4b027a
DG
251 /* Init kernel session */
252 new_session->kernel_session = NULL;
f6a9efaa 253 new_session->ust_session = NULL;
1657e9bb 254
0177d773
DG
255 /* Init lock */
256 pthread_mutex_init(&new_session->lock, NULL);
5b74c7b1 257
6df2e2c9
MD
258 new_session->uid = uid;
259 new_session->gid = gid;
260
6dc3064a
DG
261 ret = snapshot_init(&new_session->snapshot);
262 if (ret < 0) {
263 ret = LTTNG_ERR_NOMEM;
264 goto error;
265 }
266
b5541356 267 /* Add new session to the session list */
54d01ffb 268 session_lock_list();
a991f516 269 new_session->id = add_session_list(new_session);
54d01ffb 270 session_unlock_list();
b5541356 271
a4b92340
DG
272 /*
273 * Consumer is let to NULL since the create_session_uri command will set it
274 * up and, if valid, assign it to the session.
275 */
276
d022620a
DG
277 DBG("Tracing session %s created with ID %" PRIu64 " by UID %d GID %d",
278 name, new_session->id, new_session->uid, new_session->gid);
b082db07 279
f73fabfd 280 return LTTNG_OK;
5b74c7b1
DG
281
282error:
f3ed775e 283error_asprintf:
0e428499 284 free(new_session);
5b74c7b1 285
f3ed775e
DG
286error_malloc:
287 return ret;
5b74c7b1 288}
2f77fc4b
DG
289
290/*
291 * Check if the UID or GID match the session. Root user has access to all
292 * sessions.
293 */
294int session_access_ok(struct ltt_session *session, uid_t uid, gid_t gid)
295{
296 assert(session);
297
298 if (uid != session->uid && gid != session->gid && uid != 0) {
299 return 0;
300 } else {
301 return 1;
302 }
303}
This page took 0.062058 seconds and 4 git commands to generate.