Added support for optionally specifying, via a global, read-only
configuration file, system resource limits for address space, core
files, data segment size, file size, lockable memory, open files,
number of processes and stack size.

This mirrors in function, almost identically, resource limit handling
in Avahi.

  * v2: Incorporated feedback from Daniel Wagner regarding placement of the
        __connman_rlimits_init prototype.

  * v3: Incorporated coding style feedback from Daniel Wagner. Removed
        diffs from another, earlier patch.

  * v4: Incorporated more coding style feedback from Daniel Wagner.
        Removed diffs from another, earlier patch.

  * v5: White space clean-ups based on errors emitted from git am.

---
 Makefile.am                 |   23 +++--
 src/connman-dbus.conf       |   16 ---
 src/connman-polkit.conf     |   11 --
 src/connman.h               |    2 +
 src/etc/connman-dbus.conf   |   16 +++
 src/etc/connman-polkit.conf |   11 ++
 src/etc/connman.conf        |   25 +++++
 src/main.c                  |   14 +++
 src/rlimits.c               |  234 +++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 318 insertions(+), 34 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 3ad1ee9..d0443b1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,7 @@
 
 AM_MAKEFLAGS = --no-print-directory
 
+pkgsysconfdir=$(sysconfdir)/@PACKAGE@
 includedir = @includedir@/connman
 
 include_HEADERS = include/types.h include/log.h include/plugin.h \
@@ -33,6 +34,10 @@ gweb_sources = gweb/gweb.h gweb/gweb.c gweb/gresolv.h 
gweb/gresolv.c \
 
 if DATAFILES
 
+connmanconfdir = $(pkgsysconfdir)
+
+connmanconf_DATA = src/etc/connman.conf
+
 if NMCOMPAT
 nmcompat_conf = plugins/connman-nmcompat.conf
 endif
@@ -74,7 +79,8 @@ src_connmand_SOURCES = $(gdbus_sources) $(gdhcp_sources) \
                        src/resolver.c src/ipconfig.c src/detect.c src/inet.c \
                        src/dhcp.c src/rtnl.c src/proxy.c \
                        src/utsname.c src/timeserver.c src/rfkill.c \
-                       src/wifi.c src/storage.c src/dbus.c src/config.c \
+                       src/wifi.c src/storage.c src/rlimits.c \
+                       src/dbus.c src/config.c \
                        src/technology.c src/counter.c src/location.c \
                        src/session.c src/tethering.c src/wpad.c src/wispr.c \
                        src/stats.c src/iptables.c src/dnsproxy.c
@@ -110,11 +116,14 @@ AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @CAPNG_CFLAGS@ 
@XTABLES_CFLAGS@ \
                                -DSTATEDIR=\""$(statedir)"\" \
                                -DPLUGINDIR=\""$(build_plugindir)"\" \
                                -DSCRIPTDIR=\""$(build_scriptdir)"\" \
-                               -DSTORAGEDIR=\""$(storagedir)\""
+                               -DSTORAGEDIR=\""$(storagedir)"\" \
+                               -DCONFDIR=\""$(pkgsysconfdir)"\" \
+                               
-DCONNMAN_CONF_FILE=\""$(pkgsysconfdir)/connman.conf"\"
 
-INCLUDES = -I$(builddir)/include -I$(builddir)/src -I$(srcdir)/gdbus
+INCLUDES = -I$(srcdir)/include -I$(builddir)/include -I$(builddir)/src 
-I$(srcdir)/gdbus
 
-EXTRA_DIST = src/genbuiltin src/connman-dbus.conf src/connman-polkit.conf \
+EXTRA_DIST = src/genbuiltin src/etc/connman.conf \
+               src/etc/connman-dbus.conf src/etc/connman-polkit.conf \
                plugins/connman-nmcompat.conf
 
 
@@ -233,11 +242,11 @@ src/plugin.$(OBJEXT): src/builtin.h
 src/builtin.h: src/genbuiltin $(builtin_sources)
        $(AM_V_GEN)$(srcdir)/src/genbuiltin $(builtin_modules) > $@
 
-src/connman.conf: src/connman-dbus.conf src/connman-polkit.conf
+src/connman.conf: src/etc/connman-dbus.conf src/etc/connman-polkit.conf
 if POLKIT
-       $(AM_V_GEN)cp $(srcdir)/src/connman-polkit.conf $@
+       $(AM_V_GEN)cp $(srcdir)/src/etc/connman-polkit.conf $@
 else
-       $(AM_V_GEN)cp $(srcdir)/src/connman-dbus.conf $@
+       $(AM_V_GEN)cp $(srcdir)/src/etc/connman-dbus.conf $@
 endif
 
 $(src_connmand_OBJECTS) $(plugin_objects): $(local_headers)
diff --git a/src/connman-dbus.conf b/src/connman-dbus.conf
deleted file mode 100644
index 311f28c..0000000
--- a/src/connman-dbus.conf
+++ /dev/null
@@ -1,16 +0,0 @@
-<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 
1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd";>
-<busconfig>
-    <policy user="root">
-        <allow own="net.connman"/>
-        <allow send_destination="net.connman"/>
-        <allow send_interface="net.connman.Agent"/>
-        <allow send_interface="net.connman.Counter"/>
-    </policy>
-    <policy at_console="true">
-        <allow send_destination="net.connman"/>
-    </policy>
-    <policy context="default">
-        <deny send_destination="net.connman"/>
-    </policy>
-</busconfig>
diff --git a/src/connman-polkit.conf b/src/connman-polkit.conf
deleted file mode 100644
index fdddb29..0000000
--- a/src/connman-polkit.conf
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 
1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd";>
-<busconfig>
-    <policy user="root">
-        <allow own="net.connman"/>
-        <allow send_interface="net.connman.Agent"/>
-    </policy>
-    <policy context="default">
-        <allow send_destination="net.connman"/>
-    </policy>
-</busconfig>
diff --git a/src/connman.h b/src/connman.h
index 42bf2e6..d0b87b2 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -636,3 +636,5 @@ void __connman_dnsproxy_cleanup(void);
 int __connman_dnsproxy_append(const char *interface, const char *domain, const 
char *server);
 int __connman_dnsproxy_remove(const char *interface, const char *domain, const 
char *server);
 void __connman_dnsproxy_flush(void);
+
+int __connman_rlimits_init(const gchar *path);
diff --git a/src/etc/connman-dbus.conf b/src/etc/connman-dbus.conf
new file mode 100644
index 0000000..311f28c
--- /dev/null
+++ b/src/etc/connman-dbus.conf
@@ -0,0 +1,16 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 
1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd";>
+<busconfig>
+    <policy user="root">
+        <allow own="net.connman"/>
+        <allow send_destination="net.connman"/>
+        <allow send_interface="net.connman.Agent"/>
+        <allow send_interface="net.connman.Counter"/>
+    </policy>
+    <policy at_console="true">
+        <allow send_destination="net.connman"/>
+    </policy>
+    <policy context="default">
+        <deny send_destination="net.connman"/>
+    </policy>
+</busconfig>
diff --git a/src/etc/connman-polkit.conf b/src/etc/connman-polkit.conf
new file mode 100644
index 0000000..fdddb29
--- /dev/null
+++ b/src/etc/connman-polkit.conf
@@ -0,0 +1,11 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 
1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd";>
+<busconfig>
+    <policy user="root">
+        <allow own="net.connman"/>
+        <allow send_interface="net.connman.Agent"/>
+    </policy>
+    <policy context="default">
+        <allow send_destination="net.connman"/>
+    </policy>
+</busconfig>
diff --git a/src/etc/connman.conf b/src/etc/connman.conf
new file mode 100644
index 0000000..810fc6d
--- /dev/null
+++ b/src/etc/connman.conf
@@ -0,0 +1,25 @@
+# This file is part of Connection Manager.
+#
+# Connection Manager is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version
+# 2 as published by the Free Software Foundation.
+#
+# Connection Manager 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 St, Fifth Floor, Boston, MA 02110-1301
+# USA
+
+[rlimits]
+rlimit-as=5242880
+rlimit-core=0
+rlimit-data=5242880
+#rlimit-fsize=0
+rlimit-nofile=768
+rlimit-stack=5242880
+rlimit-nproc=3
+rlimit-memlock=0
diff --git a/src/main.c b/src/main.c
index ac90b5e..5dc6125 100644
--- a/src/main.c
+++ b/src/main.c
@@ -58,6 +58,7 @@ static void disconnect_callback(DBusConnection *conn, void 
*user_data)
 
 static gchar *option_debug = NULL;
 static gchar *option_device = NULL;
+static gchar *option_file = NULL;
 static gchar *option_plugin = NULL;
 static gchar *option_nodevice = NULL;
 static gchar *option_noplugin = NULL;
@@ -66,6 +67,7 @@ static gboolean option_detach = TRUE;
 static gboolean option_dnsproxy = TRUE;
 static gboolean option_compat = FALSE;
 static gboolean option_version = FALSE;
+static gboolean option_rlimits = TRUE;
 
 static gboolean parse_debug(const char *key, const char *value,
                                        gpointer user_data, GError **error)
@@ -84,6 +86,9 @@ static GOptionEntry options[] = {
                                "Specify debug options to enable", "DEBUG" },
        { "device", 'i', 0, G_OPTION_ARG_STRING, &option_device,
                        "Specify networking device or interface", "DEV" },
+       { "file", 'f', 0, G_OPTION_ARG_STRING, &option_file,
+                               "Load the specified configuration file "
+                               "instead of " CONNMAN_CONF_FILE, "FILE" },
        { "nodevice", 'I', 0, G_OPTION_ARG_STRING, &option_nodevice,
                        "Specify networking interface to ignore", "DEV" },
        { "plugin", 'p', 0, G_OPTION_ARG_STRING, &option_plugin,
@@ -98,6 +103,9 @@ static GOptionEntry options[] = {
        { "nodnsproxy", 'r', G_OPTION_FLAG_REVERSE,
                                G_OPTION_ARG_NONE, &option_dnsproxy,
                                "Don't enable DNS Proxy" },
+       { "norlimits", 0, G_OPTION_FLAG_REVERSE,
+                               G_OPTION_ARG_NONE, &option_rlimits,
+                               "Don't enforce resource limits" },
        { "compat", 'c', 0, G_OPTION_ARG_NONE, &option_compat,
                                "(obsolete)" },
        { "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
@@ -206,6 +214,10 @@ int main(int argc, char *argv[])
 
        __connman_log_init(option_debug, option_detach);
 
+       if (option_rlimits)
+               __connman_rlimits_init(option_file ? option_file :
+                                      CONNMAN_CONF_FILE);
+
        __connman_dbus_init(conn);
 
        __connman_storage_init();
@@ -234,7 +246,9 @@ int main(int argc, char *argv[])
 
        __connman_element_start();
 
+       g_free(option_debug);
        g_free(option_device);
+       g_free(option_file);
        g_free(option_plugin);
        g_free(option_nodevice);
        g_free(option_noplugin);
diff --git a/src/rlimits.c b/src/rlimits.c
new file mode 100644
index 0000000..ff43cf9
--- /dev/null
+++ b/src/rlimits.c
@@ -0,1 +1,234 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *  Copyright (C) 2011 Grant Erickson <maratho...@gmail.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 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 St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+
+#include <sys/resource.h>
+
+#include <glib.h>
+
+#include <connman/log.h>
+
+#define CONNMAN_RLIMIT_SET(r, lp, err, label)                          \
+       do {                                                            \
+               err = __connman_rlimit_set(r, lp, #r);                  \
+               if (err < 0)                                            \
+                       goto label;                                     \
+       } while (0)
+
+struct connman_rlimit {
+       gboolean set;
+       rlim_t limit;
+};
+
+struct connman_rlimits {
+#if defined(RLIMIT_AS)
+       struct connman_rlimit as;
+#endif
+       struct connman_rlimit core, data, fsize, nofile, stack;
+#if defined(RLIMIT_MEMLOCK)
+       struct connman_rlimit memlock;
+#endif
+#if defined(RLIMIT_NPROC)
+       struct connman_rlimit nproc;
+#endif
+};
+
+#if defined(RLIMIT_AS)
+static const char * RLIMIT_AS_KEY      = "rlimit-as";
+#endif
+static const char * RLIMIT_CORE_KEY    = "rlimit-core";
+static const char * RLIMIT_DATA_KEY    = "rlimit-data";
+static const char * RLIMIT_FSIZE_KEY   = "rlimit-fsize";
+static const char * RLIMIT_NOFILE_KEY  = "rlimit-nofile";
+static const char * RLIMIT_STACK_KEY   = "rlimit-stack";
+#if defined(RLIMIT_NPROC)
+static const char * RLIMIT_NPROC_KEY   = "rlimit-nproc";
+#endif
+#if defined(RLIMIT_MEMLOCK)
+static const char * RLIMIT_MEMLOCK_KEY = "rlimit-memlock";
+#endif
+
+static int set_one_rlimit(int resource, rlim_t limit, const char *name)
+{
+       int err;
+       struct rlimit rl;
+       rl.rlim_cur = rl.rlim_max = limit;
+
+       DBG("resource %d limit %u name %s", resource, (unsigned)limit, name);
+
+       err = setrlimit(resource, &rl);
+
+       if (err < 0) {
+               connman_warn("setrlimit(%s, {%u, %u}) failed: %s",
+                            name, (unsigned)limit,
+                            (unsigned)limit,
+                            strerror(errno));
+
+               return -errno;
+       }
+
+       return err;
+}
+
+static inline int __connman_rlimit_set(int resource,
+                                      const struct connman_rlimit *limit,
+                                      const char *name)
+{
+       int err = 0;
+
+       if (limit->set)
+               err = set_one_rlimit(resource, limit->limit, name);
+
+       return err;
+}
+
+static int __connman_rlimits_enforce(const struct connman_rlimits *limits)
+{
+       int err;
+
+       if (limits == NULL)
+               return 0;
+
+#if defined(RLIMIT_AS)
+       CONNMAN_RLIMIT_SET(RLIMIT_AS,      &limits->as,      err, done);
+#endif
+       CONNMAN_RLIMIT_SET(RLIMIT_CORE,    &limits->core,    err, done);
+       CONNMAN_RLIMIT_SET(RLIMIT_DATA,    &limits->data,    err, done);
+       CONNMAN_RLIMIT_SET(RLIMIT_FSIZE,   &limits->fsize,   err, done);
+       CONNMAN_RLIMIT_SET(RLIMIT_NOFILE,  &limits->nofile,  err, done);
+       CONNMAN_RLIMIT_SET(RLIMIT_STACK,   &limits->stack,   err, done);
+#if defined(RLIMIT_MEMLOCK)
+       CONNMAN_RLIMIT_SET(RLIMIT_MEMLOCK, &limits->memlock, err, done);
+#endif
+#if defined(RLIMIT_NPROC)
+       CONNMAN_RLIMIT_SET(RLIMIT_NPROC,   &limits->nproc,   err, done);
+#endif
+
+ done:
+       return err;
+}
+
+static void __connman_rlimit_read(GKeyFile *keyfile, const gchar *key,
+                                 struct connman_rlimit *limit)
+{
+       const char *group = "rlimits";
+       gint temp;
+       GError *error = NULL;
+
+       if (keyfile != NULL && key != NULL && limit != NULL) {
+               temp = g_key_file_get_integer(keyfile, group, key, &error);
+
+               DBG("key %s temp %d error %p", key, temp, error);
+
+               if (error == NULL) {
+                       limit->set = TRUE;
+                       limit->limit = temp;
+               } else {
+                       limit->set = FALSE;
+                       limit->limit = 0;
+                       g_clear_error(&error);
+               }
+
+               DBG("set %u limit %u", limit->set, (unsigned)limit->limit);
+       }
+}
+
+static GKeyFile *__connman_rlimits_open(const gchar *path)
+{
+       GKeyFile *keyfile;
+       gchar *data = NULL;
+       gboolean result;
+       gsize length;
+
+       DBG("path %s", path);
+
+       result = g_file_get_contents(path, &data, &length, NULL);
+
+       keyfile = g_key_file_new();
+
+       if (result == FALSE)
+               goto done;
+
+       if (length > 0)
+               g_key_file_load_from_data(keyfile, data, length, 0, NULL);
+
+       g_free(data);
+
+done:
+       DBG("keyfile %p", keyfile);
+
+       return keyfile;
+}
+
+static int __connman_rlimits_load(const gchar *path,
+                                 struct connman_rlimits *limits)
+{
+       GKeyFile *keyfile;
+
+       if (limits == NULL)
+               return -EINVAL;
+
+       keyfile = __connman_rlimits_open(path);
+
+       if (keyfile == NULL)
+               return -EIO;
+
+#if defined(RLIMIT_AS)
+       __connman_rlimit_read(keyfile, RLIMIT_AS_KEY,      &limits->as);
+#endif
+       __connman_rlimit_read(keyfile, RLIMIT_CORE_KEY,    &limits->core);
+       __connman_rlimit_read(keyfile, RLIMIT_DATA_KEY,    &limits->data);
+       __connman_rlimit_read(keyfile, RLIMIT_FSIZE_KEY,   &limits->fsize);
+       __connman_rlimit_read(keyfile, RLIMIT_NOFILE_KEY,  &limits->nofile);
+       __connman_rlimit_read(keyfile, RLIMIT_STACK_KEY,   &limits->stack);
+#if defined(RLIMIT_NPROC)
+       __connman_rlimit_read(keyfile, RLIMIT_NPROC_KEY,   &limits->nproc);
+#endif
+#if defined(RLIMIT_MEMLOCK)
+       __connman_rlimit_read(keyfile, RLIMIT_MEMLOCK_KEY, &limits->memlock);
+#endif
+
+       g_key_file_free(keyfile);
+
+       return 0;
+}
+
+int __connman_rlimits_init(const gchar *path)
+{
+       struct connman_rlimits rlimits;
+       int err;
+
+       if (path == NULL)
+               return -EINVAL;
+
+       err = __connman_rlimits_load(path, &rlimits);
+
+       if (err < 0)
+               return err;
+
+       return __connman_rlimits_enforce(&rlimits);
+}
--
1.7.3.4
_______________________________________________
connman mailing list
connman@connman.net
http://lists.connman.net/listinfo/connman

Reply via email to