On Wed, February 18, 2009 10:31 pm, Corey Hickey wrote:
> Additionally, I can write a patch that checks the current limit and
> makes slmodemd warn or die if the limit is judged to be too low. I'm
> mildly in favor of that approach rather than having slmodemd modify the
> limit itself.
Ok, here's the patch. Feel free to tweak it as you see fit.
I'm at my mom's house right now, so I hooked up the land line, dialed, and
gave the patch a rudimentary test with actual connectivity. It seems to
work fine, even with realtime scheduling.
I hit one snag on that last point, though: it's definitely possible to
assign the Slmodemd user an insufficient realtime CPU share and have
slmodemd run poorly (lots of alsa xrun errors). Realtime processes don't
"borrow" CPU share from other processes, realtime or otherwise.
It might be worth considering a way to check for sufficient CPU share, but
I don't see how to do it in a system-neutral way (5% might be enough for
me but not for somebody else). There may be precedent in how other
realtime programs handle that situation.
Anyway, I'll have infrequent Internet access and very little availability
for the next month, so I'm not going to investigate that now. I hope this
most recent patch is useful.
-Corey
--- sl-modem-2.9.11~20080817.orig/modem/modem_main.c 2009-02-21 15:46:39.000000000 -0800
+++ sl-modem-2.9.11~20080817/modem/modem_main.c 2009-02-21 15:42:20.000000000 -0800
@@ -53,10 +53,13 @@
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/resource.h>
#include <sched.h>
#include <signal.h>
#include <limits.h>
#include <grp.h>
+#include <pwd.h>
#ifdef SUPPORT_ALSA
#define ALSA_PCM_NEW_HW_PARAMS_API 1
@@ -76,6 +79,10 @@
#define DBG(fmt,args...) dprintf("main: " fmt, ##args)
+#define SLMODEMD_USER "Slmodemd"
+#define LOCKED_MEM_MIN_KB (8UL * 1024)
+#define LOCKED_MEM_MIN (LOCKED_MEM_MIN_KB * 1024)
+
#define CLOSE_COUNT_MAX 100
@@ -936,6 +943,7 @@
struct modem *m;
int pty;
int ret = 0;
+ struct passwd *pwd;
modem_debug_init(basename(dev_name));
@@ -984,6 +992,46 @@
signal(SIGINT, mark_termination);
signal(SIGTERM, mark_termination);
+#ifdef SLMODEMD_USER
+ if (need_realtime) {
+ struct rlimit limit;
+ if (getrlimit(RLIMIT_MEMLOCK, &limit)) {
+ ERR("getrlimit failed to read RLIMIT_MEMLOCK\n");
+ exit(-1);
+ }
+ if (limit.rlim_cur != RLIM_INFINITY &&
+ limit.rlim_cur < LOCKED_MEM_MIN) {
+ ERR("locked memory limit too low:\n");
+ ERR("need %lu bytes, have %lu bytes\n", LOCKED_MEM_MIN,
+ (unsigned long)limit.rlim_cur);
+ ERR("try 'ulimit -l %lu'\n", LOCKED_MEM_MIN_KB);
+ exit(-1);
+ }
+ }
+
+ pwd = getpwnam(SLMODEMD_USER);
+ if (!pwd) {
+ ERR("getpwnam " SLMODEMD_USER ": %s\n",strerror(errno));
+ exit(-1);
+ }
+
+ ret = (setgroups(1,&pwd->pw_gid) ||
+ setgid(pwd->pw_gid) ||
+ setuid(pwd->pw_uid));
+ if (ret) {
+ ERR("setgroups or setgid %ld or setuid %ld failed: %s\n",
+ (long)pwd->pw_gid,(long)pwd->pw_uid,strerror(errno));
+ exit(-1);
+ }
+
+ if (setuid(0) != -1) {
+ ERR("setuid 0 succeeded after dropping privileges!\n");
+ exit(-1);
+ }
+ DBG("dropped privileges to %ld.%ld\n",
+ (long)pwd->pw_gid,(long)pwd->pw_uid);
+#endif
+
INFO("Use `%s' as modem device, Ctrl+C for termination.\n",
*link_name ? link_name : m->pty_name);
--- sl-modem-2.9.11~20080817.orig/debian/patches/10_drop_privileges.diff 2009-02-16 13:37:34.000000000 -0800
+++ sl-modem-2.9.11~20080817/debian/patches/10_drop_privileges.diff 2009-02-21 15:47:06.000000000 -0800
@@ -1,9 +1,12 @@
-slmodemd privilege dropping patch.
-Index: slmodem-2.9.11-20080817/modem/modem_main.c
-===================================================================
---- slmodem-2.9.11-20080817.orig/modem/modem_main.c 2008-09-18 08:19:43.000000000 +0200
-+++ slmodem-2.9.11-20080817/modem/modem_main.c 2008-09-18 08:20:24.000000000 +0200
-@@ -57,6 +57,7 @@
+--- sl-modem-2.9.11~20080817.orig/modem/modem_main.c 2009-02-21 15:46:39.000000000 -0800
++++ sl-modem-2.9.11~20080817/modem/modem_main.c 2009-02-21 15:42:20.000000000 -0800
+@@ -53,10 +53,13 @@
+ #include <sys/stat.h>
+ #include <sys/ioctl.h>
+ #include <sys/mman.h>
++#include <sys/time.h>
++#include <sys/resource.h>
+ #include <sched.h>
#include <signal.h>
#include <limits.h>
#include <grp.h>
@@ -11,16 +14,18 @@
#ifdef SUPPORT_ALSA
#define ALSA_PCM_NEW_HW_PARAMS_API 1
-@@ -76,6 +77,8 @@
+@@ -76,6 +79,10 @@
#define DBG(fmt,args...) dprintf("main: " fmt, ##args)
+#define SLMODEMD_USER "Slmodemd"
++#define LOCKED_MEM_MIN_KB (8UL * 1024)
++#define LOCKED_MEM_MIN (LOCKED_MEM_MIN_KB * 1024)
+
#define CLOSE_COUNT_MAX 100
-@@ -936,6 +939,7 @@
+@@ -936,6 +943,7 @@
struct modem *m;
int pty;
int ret = 0;
@@ -28,11 +33,27 @@
modem_debug_init(basename(dev_name));
-@@ -984,6 +988,30 @@
+@@ -984,6 +992,46 @@
signal(SIGINT, mark_termination);
signal(SIGTERM, mark_termination);
+#ifdef SLMODEMD_USER
++ if (need_realtime) {
++ struct rlimit limit;
++ if (getrlimit(RLIMIT_MEMLOCK, &limit)) {
++ ERR("getrlimit failed to read RLIMIT_MEMLOCK\n");
++ exit(-1);
++ }
++ if (limit.rlim_cur != RLIM_INFINITY &&
++ limit.rlim_cur < LOCKED_MEM_MIN) {
++ ERR("locked memory limit too low:\n");
++ ERR("need %lu bytes, have %lu bytes\n", LOCKED_MEM_MIN,
++ (unsigned long)limit.rlim_cur);
++ ERR("try 'ulimit -l %lu'\n", LOCKED_MEM_MIN_KB);
++ exit(-1);
++ }
++ }
++
+ pwd = getpwnam(SLMODEMD_USER);
+ if (!pwd) {
+ ERR("getpwnam " SLMODEMD_USER ": %s\n",strerror(errno));