[lttng-dev] [lttng-tools PATCH] Keep track of FD used for UST applications
Mathieu Desnoyers
mathieu.desnoyers at efficios.com
Mon Mar 19 22:55:32 EDT 2012
Allow to keep 25% of file descriptors reserved for commands/kernel
tracing/internal communication within the sessiond by limiting
applications to 75% of the available file descriptors. This ensures
traced applications cannot cause a sessiond denial of service.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers at efficios.com>
---
diff --git a/src/bin/lttng-sessiond/Makefile.am b/src/bin/lttng-sessiond/Makefile.am
index ccdbe3a..8748dd6 100644
--- a/src/bin/lttng-sessiond/Makefile.am
+++ b/src/bin/lttng-sessiond/Makefile.am
@@ -16,7 +16,8 @@ lttng_sessiond_SOURCES = utils.c utils.h \
shm.c shm.h \
session.c session.h \
modprobe.c modprobe.h kern-modules.h \
- lttng-ust-ctl.h lttng-ust-abi.h
+ lttng-ust-ctl.h lttng-ust-abi.h \
+ fd-limit.c fd-limit.h
if HAVE_LIBLTTNG_UST_CTL
lttng_sessiond_SOURCES += trace-ust.c ust-app.c ust-consumer.c ust-consumer.h
diff --git a/src/bin/lttng-sessiond/fd-limit.c b/src/bin/lttng-sessiond/fd-limit.c
new file mode 100644
index 0000000..a886d33
--- /dev/null
+++ b/src/bin/lttng-sessiond/fd-limit.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2012 - Mathieu Desnoyers <mathieu.desnoyers at efficios.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _GNU_SOURCE
+#include <urcu/uatomic.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <errno.h>
+#include <stdio.h>
+#include "fd-limit.h"
+
+/* total count of fd. */
+static long fd_count;
+
+/*
+ * threshold in % of number of fd allowed.
+ */
+static long fd_threshold[LTTNG_FD_NR_TYPES] = {
+ [LTTNG_FD_APPS] = 75,
+};
+
+static rlim_t max_nr_fd;
+
+int lttng_fd_get(enum lttng_fd_type type, unsigned int nr)
+{
+ long newval;
+
+ if (type >= LTTNG_FD_NR_TYPES) {
+ return -EINVAL;
+ }
+
+ newval = uatomic_add_return(&fd_count, (long) nr);
+ if ((long) (newval * 100)
+ - (long) (max_nr_fd * fd_threshold[type]) > 0) {
+ uatomic_sub(&fd_count, (long) nr);
+ return -EPERM;
+ }
+ return 0;
+}
+
+void lttng_fd_put(enum lttng_fd_type type, unsigned int nr)
+{
+ uatomic_sub(&fd_count, (long) nr);
+}
+
+void lttng_fd_init(void)
+{
+ struct rlimit rlim;
+ int ret;
+
+ ret = getrlimit(RLIMIT_NOFILE, &rlim);
+ if (ret < 0) {
+ perror("getrlimit");
+ }
+ max_nr_fd = rlim.rlim_cur;
+}
diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c
index 0c4d4b1..e94d38b 100644
--- a/src/bin/lttng-sessiond/main.c
+++ b/src/bin/lttng-sessiond/main.c
@@ -54,6 +54,7 @@
#include "shm.h"
#include "ust-ctl.h"
#include "utils.h"
+#include "fd-limit.h"
#define CONSUMERD_FILE "lttng-consumerd"
@@ -1424,6 +1425,17 @@ static void *thread_registration_apps(void *data)
* Using message-based transmissions to ensure we don't
* have to deal with partially received messages.
*/
+ ret = lttng_fd_get(LTTNG_FD_APPS, 1);
+ if (ret < 0) {
+ ERR("Exhausted file descriptors allowed for applications.");
+ free(ust_cmd);
+ ret = close(sock);
+ if (ret) {
+ PERROR("close");
+ }
+ sock = -1;
+ continue;
+ }
ret = lttcomm_recv_unix_sock(sock, &ust_cmd->reg_msg,
sizeof(struct ust_register_msg));
if (ret < 0 || ret < sizeof(struct ust_register_msg)) {
@@ -1437,6 +1449,7 @@ static void *thread_registration_apps(void *data)
if (ret) {
PERROR("close");
}
+ lttng_fd_put(LTTNG_FD_APPS, 1);
sock = -1;
continue;
}
@@ -1482,6 +1495,7 @@ error:
if (ret) {
PERROR("close");
}
+ lttng_fd_put(LTTNG_FD_APPS, 1);
}
unlink(apps_unix_sock_path);
@@ -4544,6 +4558,8 @@ int main(int argc, char **argv)
/* Set ulimit for open files */
set_ulimit();
}
+ /* init lttng_fd tracking must be done after set_ulimit. */
+ lttng_fd_init();
ret = set_consumer_sockets(&ustconsumer64_data, rundir);
if (ret < 0) {
diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c
index 79526fc..7dbea5c 100644
--- a/src/bin/lttng-sessiond/ust-app.c
+++ b/src/bin/lttng-sessiond/ust-app.c
@@ -31,6 +31,7 @@
#include "ust-app.h"
#include "ust-consumer.h"
#include "ust-ctl.h"
+#include "fd-limit.h"
/*
* Delete ust context safely. RCU read lock must be held before calling
@@ -82,6 +83,7 @@ void delete_ust_app_stream(int sock, struct ltt_ust_stream *stream)
{
if (stream->obj) {
ustctl_release_object(sock, stream->obj);
+ lttng_fd_put(LTTNG_FD_APPS, 2);
free(stream->obj);
}
free(stream);
@@ -125,6 +127,7 @@ void delete_ust_app_channel(int sock, struct ust_app_channel *ua_chan)
if (ua_chan->obj != NULL) {
ustctl_release_object(sock, ua_chan->obj);
+ lttng_fd_put(LTTNG_FD_APPS, 2);
free(ua_chan->obj);
}
free(ua_chan);
@@ -144,10 +147,12 @@ void delete_ust_app_session(int sock, struct ust_app_session *ua_sess)
if (ua_sess->metadata) {
if (ua_sess->metadata->stream_obj) {
ustctl_release_object(sock, ua_sess->metadata->stream_obj);
+ lttng_fd_put(LTTNG_FD_APPS, 2);
free(ua_sess->metadata->stream_obj);
}
if (ua_sess->metadata->obj) {
ustctl_release_object(sock, ua_sess->metadata->obj);
+ lttng_fd_put(LTTNG_FD_APPS, 2);
free(ua_sess->metadata->obj);
}
trace_ust_destroy_metadata(ua_sess->metadata);
@@ -210,6 +215,7 @@ void delete_ust_app(struct ust_app *app)
if (ret) {
PERROR("close");
}
+ lttng_fd_put(LTTNG_FD_APPS, 1);
DBG2("UST app pid %d deleted", app->pid);
free(app);
@@ -536,6 +542,12 @@ static int open_ust_metadata(struct ust_app *app,
ua_sess->metadata->attr.read_timer_interval;
uattr.output = ua_sess->metadata->attr.output;
+ /* We are going to receive 2 fds, we need to reserve them. */
+ ret = lttng_fd_get(LTTNG_FD_APPS, 2);
+ if (ret < 0) {
+ ERR("Exhausted number of available FD upon metadata open");
+ goto error;
+ }
/* UST tracer metadata creation */
ret = ustctl_open_metadata(app->sock, ua_sess->handle, &uattr,
&ua_sess->metadata->obj);
@@ -559,6 +571,12 @@ static int create_ust_stream(struct ust_app *app,
{
int ret;
+ /* We are going to receive 2 fds, we need to reserve them. */
+ ret = lttng_fd_get(LTTNG_FD_APPS, 2);
+ if (ret < 0) {
+ ERR("Exhausted number of available FD upon metadata stream create");
+ goto error;
+ }
ret = ustctl_create_stream(app->sock, ua_sess->metadata->obj,
&ua_sess->metadata->stream_obj);
if (ret < 0) {
@@ -579,6 +597,13 @@ static int create_ust_channel(struct ust_app *app,
int ret;
/* TODO: remove cast and use lttng-ust-abi.h */
+
+ /* We are going to receive 2 fds, we need to reserve them. */
+ ret = lttng_fd_get(LTTNG_FD_APPS, 2);
+ if (ret < 0) {
+ ERR("Exhausted number of available FD upon create channel");
+ goto error;
+ }
ret = ustctl_create_channel(app->sock, ua_sess->handle,
(struct lttng_ust_channel_attr *)&ua_chan->attr, &ua_chan->obj);
if (ret < 0) {
@@ -586,6 +611,7 @@ static int create_ust_channel(struct ust_app *app,
"and session handle %d with ret %d",
ua_chan->name, app->pid, app->sock,
ua_sess->handle, ret);
+ lttng_fd_put(LTTNG_FD_APPS, 2);
goto error;
}
@@ -1281,6 +1307,7 @@ int ust_app_register(struct ust_register_msg *msg, int sock)
if (ret) {
PERROR("close");
}
+ lttng_fd_put(LTTNG_FD_APPS, 1);
return -EINVAL;
}
if (msg->major != LTTNG_UST_COMM_MAJOR) {
@@ -1291,6 +1318,7 @@ int ust_app_register(struct ust_register_msg *msg, int sock)
if (ret) {
PERROR("close");
}
+ lttng_fd_put(LTTNG_FD_APPS, 1);
return -EINVAL;
}
lta = zmalloc(sizeof(struct ust_app));
@@ -1977,10 +2005,18 @@ int ust_app_start_trace(struct ltt_ust_session *usess, struct ust_app *app)
goto error_rcu_unlock;
}
+ /* We are going to receive 2 fds, we need to reserve them. */
+ ret = lttng_fd_get(LTTNG_FD_APPS, 2);
+ if (ret < 0) {
+ ERR("Exhausted number of available FD upon stream create");
+ free(ustream);
+ goto error_rcu_unlock;
+ }
ret = ustctl_create_stream(app->sock, ua_chan->obj,
&ustream->obj);
if (ret < 0) {
/* Got all streams */
+ lttng_fd_put(LTTNG_FD_APPS, 2);
free(ustream);
break;
}
--
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com
More information about the lttng-dev
mailing list