summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Lebl <jirka@5z.com>2003-09-12 21:50:46 +0000
committerGeorge Lebl <jirka@src.gnome.org>2003-09-12 21:50:46 +0000
commitdde96cfce197fe25b39412a0c9892b70d15470a0 (patch)
tree01bd52a9a59b19268a2d5c524ce0e4052b36344c
parent1eedcd47213dd470fc7e9a5aa3849a88cd20a8d2 (diff)
downloadgdm-dde96cfce197fe25b39412a0c9892b70d15470a0.tar.gz
raise version
Fri Sep 12 14:49:30 2003 George Lebl <jirka@5z.com> * configure.in: raise version * daemon/gdm-net.c: some cleanup and be utterly anal when creating /tmp/.gdm_socket (note: we were anal before, but now we're really REALLY anal) * daemon/gdm.c: disable substituting 'nobody' for 'gdm', what was I smoking when I wrote that? * daemon/misc.c: some cleanup and make sure gdm_fdprintf writes all the characters it really needs to write. Also the ensure extension doesn't append extensions to empty strings. * daemon/slave.c: use only one pipe for all the waitpids, since we really don't need more then one and this make code simpler. * docs/C/gdm.xml: update
-rw-r--r--ChangeLog19
-rw-r--r--TODO4
-rw-r--r--configure.in2
-rw-r--r--daemon/gdm-net.c44
-rw-r--r--daemon/gdm.c4
-rw-r--r--daemon/misc.c58
-rw-r--r--daemon/slave.c57
-rw-r--r--docs/C/gdm.xml14
8 files changed, 132 insertions, 70 deletions
diff --git a/ChangeLog b/ChangeLog
index 8ea2fb3f..4cd071ad 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+Fri Sep 12 14:49:30 2003 George Lebl <jirka@5z.com>
+
+ * configure.in: raise version
+
+ * daemon/gdm-net.c: some cleanup and be utterly anal when creating /tmp/.gdm_socket
+ (note: we were anal before, but now we're really REALLY anal)
+
+ * daemon/gdm.c: disable substituting 'nobody' for 'gdm', what was I
+ smoking when I wrote that?
+
+ * daemon/misc.c: some cleanup and make sure gdm_fdprintf writes all
+ the characters it really needs to write. Also the ensure extension
+ doesn't append extensions to empty strings.
+
+ * daemon/slave.c: use only one pipe for all the waitpids, since we
+ really don't need more then one and this make code simpler.
+
+ * docs/C/gdm.xml: update
+
Thu Sep 11 16:11:57 2003 George Lebl <jirka@5z.com>
* config/gdm.conf.in: add comment about ShowLastSession
diff --git a/TODO b/TODO
index 7b1909ff..c4ebea76 100644
--- a/TODO
+++ b/TODO
@@ -10,7 +10,9 @@ run from within the mainloop. The one thing that will always cause trouble here
is the XDMCP server pinging, I think in this case it would be sane to do the setjmp
thing and just ignore the ping if a signal comes, not sure how this will play with
the X stuff and if this would completely whack us out. The other option is to have
-a separate "pinger process" but that seems to heavyweight.
+a separate "pinger process" but that seems to heavyweight. Another option here
+is to give up on complete mainloopishness and during pinging set up an alarm or
+some other polling thing that checks all the mainloops stuff.
All the GUIs running as the gdm user should have some resource limits set to
make it hard to do DoS attacks by somehow exploiting a leak or some such.
diff --git a/configure.in b/configure.in
index f5cf8699..2fc3094c 100644
--- a/configure.in
+++ b/configure.in
@@ -8,7 +8,7 @@ dnl
AC_PROG_INTLTOOL([0.21])
AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE(gdm,2.4.4.0)
+AM_INIT_AUTOMAKE(gdm,2.4.4.1)
AM_MAINTAINER_MODE
GTK_REQUIRED=1.3.1
diff --git a/daemon/gdm-net.c b/daemon/gdm-net.c
index 8da6a788..6e91dab5 100644
--- a/daemon/gdm-net.c
+++ b/daemon/gdm-net.c
@@ -154,7 +154,7 @@ gdm_connection_write (GdmConnection *conn, const char *str)
g_return_val_if_fail (conn != NULL, FALSE);
g_return_val_if_fail (str != NULL, FALSE);
- if ( ! conn->writable)
+ if G_UNLIKELY ( ! conn->writable)
return FALSE;
#ifdef MSG_NOSIGNAL
@@ -165,7 +165,7 @@ gdm_connection_write (GdmConnection *conn, const char *str)
signal (SIGPIPE, old_handler);
#endif
- if (ret < 0)
+ if G_UNLIKELY (ret < 0)
return FALSE;
else
return TRUE;
@@ -189,7 +189,7 @@ gdm_socket_handler (GIOChannel *source,
IGNORE_EINTR (fd = accept (conn->fd,
(struct sockaddr *)&addr,
&addr_size));
- if (fd < 0) {
+ if G_UNLIKELY (fd < 0) {
gdm_debug ("gdm_socket_handler: Rejecting connection");
return TRUE;
}
@@ -240,23 +240,47 @@ gdm_connection_open_unix (const char *sockname, mode_t mode)
GdmConnection *conn;
struct sockaddr_un addr;
int fd;
-
- IGNORE_EINTR (unlink (sockname));
+ int try_again_attempts = 1000;
fd = socket (AF_UNIX, SOCK_STREAM, 0);
- if (fd < 0) {
+ if G_UNLIKELY (fd < 0) {
gdm_error (_("%s: Could not make socket"),
"gdm_connection_open_unix");
return NULL;
}
+try_again:
+ /* this is all for creating sockets in /tmp/ safely */
+ IGNORE_EINTR (unlink (sockname));
+ if G_UNLIKELY (errno == EISDIR ||
+ errno == EPERM) {
+ /* likely a directory, someone's playing tricks on us */
+ char *newname = NULL;
+ do {
+ g_free (newname);
+ newname = g_strdup_printf ("%s-renamed-%u",
+ sockname,
+ (guint)g_random_int ());
+ } while (access (newname, F_OK) == 0);
+ IGNORE_EINTR (rename (sockname, newname));
+ if G_UNLIKELY (errno != 0)
+ try_again_attempts = 0;
+ g_free (newname);
+ } else if G_UNLIKELY (errno != 0) {
+ try_again_attempts = 0;
+ }
+
memset(&addr, 0, sizeof(addr));
strcpy (addr.sun_path, sockname);
addr.sun_family = AF_UNIX;
- if (bind (fd,
- (struct sockaddr *) &addr, sizeof (addr)) < 0) {
+ if G_UNLIKELY (bind (fd,
+ (struct sockaddr *) &addr, sizeof (addr)) < 0) {
gdm_error (_("%s: Could not bind socket"),
"gdm_connection_open_unix");
+ try_again_attempts --;
+ /* someone is being evil on us */
+ if (errno == EADDRINUSE && try_again_attempts >= 0)
+ goto try_again;
IGNORE_EINTR (close (fd));
return NULL;
}
@@ -330,7 +354,7 @@ gdm_connection_open_fifo (const char *fifo, mode_t mode)
IGNORE_EINTR (unlink (fifo));
- if (mkfifo (fifo, 0660) < 0) {
+ if G_UNLIKELY (mkfifo (fifo, 0660) < 0) {
gdm_error (_("%s: Could not make FIFO"),
"gdm_connection_open_fifo");
return NULL;
@@ -338,7 +362,7 @@ gdm_connection_open_fifo (const char *fifo, mode_t mode)
fd = open (fifo, O_RDWR); /* Open with write to avoid EOF */
- if (fd < 0) {
+ if G_UNLIKELY (fd < 0) {
gdm_error (_("%s: Could not open FIFO"),
"gdm_connection_open_fifo");
return NULL;
diff --git a/daemon/gdm.c b/daemon/gdm.c
index 50b7c76e..08cac6a5 100644
--- a/daemon/gdm.c
+++ b/daemon/gdm.c
@@ -607,7 +607,7 @@ gdm_config_parse (void)
/* Lookup user and groupid for the gdm user */
pwent = getpwnam (GdmUser);
- if G_UNLIKELY (pwent == NULL) {
+ if G_UNLIKELY (pwent == NULL && 0 /* FIXME: this is evil! */) {
gdm_error (_("%s: Can't find the gdm user (%s). Trying 'nobody'!"), "gdm_config_parse", GdmUser);
g_free (GdmUser);
GdmUser = g_strdup ("nobody");
@@ -643,7 +643,7 @@ gdm_config_parse (void)
grent = getgrnam (GdmGroup);
- if G_UNLIKELY (grent == NULL) {
+ if G_UNLIKELY (grent == NULL && 0 /* FIXME: this is evil! */) {
gdm_error (_("%s: Can't find the gdm group (%s). Trying 'nobody'!"), "gdm_config_parse", GdmUser);
g_free (GdmGroup);
GdmGroup = g_strdup ("nobody");
diff --git a/daemon/misc.c b/daemon/misc.c
index 4b582b39..266b3268 100644
--- a/daemon/misc.c
+++ b/daemon/misc.c
@@ -216,12 +216,28 @@ gdm_fdprintf (int fd, const gchar *format, ...)
{
va_list args;
gchar *s;
+ int written, len;
va_start (args, format);
s = g_strdup_vprintf (format, args);
va_end (args);
- IGNORE_EINTR (write (fd, s, strlen (s)));
+ len = strlen (s);
+
+ if (len == 0) {
+ g_free (s);
+ return;
+ }
+
+ written = 0;
+ while (written < len) {
+ int w;
+ IGNORE_EINTR (w = write (fd, &s[written], len - written));
+ if (w < 0)
+ /* evil! */
+ break;
+ written += w;
+ }
g_free (s);
}
@@ -775,9 +791,9 @@ gdm_wait_for_extra (int *status)
gdm_sigchld_block_pop ();
}
-/* done before each login. This can do so sanity ensuring,
- * one of the things it does now is make sure /tmp/.ICE-unix
- * exists and has the correct permissions */
+/* done before each login and on startup. This can do some
+ * sanity ensuring, one of the things it does now is make
+ * sure /tmp/.ICE-unix exists and has the correct permissions */
void
gdm_ensure_sanity (void)
{
@@ -796,20 +812,20 @@ gdm_ensure_sanity (void)
* if we can't perform this task :) */
old_umask = umask (0);
- if (mkdir ("/tmp/.ICE-unix", 01777) != 0) {
+ if G_UNLIKELY (mkdir ("/tmp/.ICE-unix", 01777) != 0) {
/* if we can't create it, perhaps it
already exists, in which case ensure the
correct permissions */
struct stat s;
int r;
IGNORE_EINTR (r = lstat ("/tmp/.ICE-unix", &s));
- if (r == 0 && S_ISDIR (s.st_mode)) {
+ if G_LIKELY (r == 0 && S_ISDIR (s.st_mode)) {
/* Make sure it is root and sticky */
IGNORE_EINTR (chown ("/tmp/.ICE-unix", 0, 0));
IGNORE_EINTR (chmod ("/tmp/.ICE-unix", 01777));
} else {
/* There is a file/link/whatever called .ICE-unix? whack and try mkdir */
- unlink ("/tmp/.ICE-unix");
+ IGNORE_EINTR (unlink ("/tmp/.ICE-unix"));
mkdir ("/tmp/.ICE-unix", 01777);
}
}
@@ -910,7 +926,7 @@ gdm_peek_local_address_list (void)
/* host based fallback, will likely only get 127.0.0.1 i think */
hostbuf[BUFSIZ-1] = '\0';
- if (gethostname (hostbuf, BUFSIZ-1) != 0) {
+ if G_UNLIKELY (gethostname (hostbuf, BUFSIZ-1) != 0) {
gdm_debug ("%s: Could not get server hostname: %s!",
"gdm_peek_local_address_list",
strerror (errno));
@@ -919,7 +935,7 @@ gdm_peek_local_address_list (void)
return g_list_append (NULL, addr);
}
he = gethostbyname (hostbuf);
- if (he == NULL) {
+ if G_UNLIKELY (he == NULL) {
gdm_debug ("%s: Could not get address from hostname!",
"gdm_peek_local_address_list");
addr = g_new0 (struct in_addr, 1);
@@ -1136,20 +1152,20 @@ gdm_close_all_descriptors (int from, int except, int except2)
dir = opendir ("/proc/self/fd/"); /* This is the Linux dir */
if (dir == NULL)
dir = opendir ("/dev/fd/"); /* This is the FreeBSD dir */
- if (dir != NULL) {
+ if G_LIKELY (dir != NULL) {
GSList *li;
while ((ent = readdir (dir)) != NULL) {
+ int fd;
if (ent->d_name[0] == '.')
continue;
- openfds = g_slist_prepend (openfds,
- GINT_TO_POINTER (atoi (ent->d_name)));
+ fd = atoi (ent->d_name);
+ if (fd >= from && fd != except && fd != except2)
+ openfds = g_slist_prepend (openfds, GINT_TO_POINTER (fd));
}
closedir (dir);
for (li = openfds; li != NULL; li = li->next) {
int fd = GPOINTER_TO_INT (li->data);
- if (fd >= from && fd != except && fd != except2) {
- IGNORE_EINTR (close(fd));
- }
+ IGNORE_EINTR (close(fd));
}
g_slist_free (openfds);
} else {
@@ -1158,7 +1174,7 @@ gdm_close_all_descriptors (int from, int except, int except2)
/* don't go higher then this. This is
* a safety measure to not hang on crazy
* systems */
- if (max > 4096) {
+ if G_UNLIKELY (max > 4096) {
/* FIXME: warn about this perhaps */
/* try an open, in case we're really
leaking fds somewhere badly, this
@@ -1167,7 +1183,7 @@ gdm_close_all_descriptors (int from, int except, int except2)
max = MAX (i+1, 4096);
}
for (i = from; i < max; i++) {
- if (i != except && i != except2)
+ if G_LIKELY (i != except && i != except2)
IGNORE_EINTR (close(i));
}
}
@@ -1822,7 +1838,12 @@ gdm_make_filename (const char *dir, const char *name, const char *extension)
char *
gdm_ensure_extension (const char *name, const char *extension)
{
- const char *p = strrchr (name, '.');
+ const char *p;
+
+ if (ve_string_empty (name))
+ return g_strdup (name);
+
+ p = strrchr (name, '.');
if (p != NULL &&
strcmp (p, extension) == 0) {
return g_strdup (name);
@@ -1837,7 +1858,6 @@ gdm_strip_extension (const char *name, const char *extension)
const char *p = strrchr (name, '.');
if (p != NULL &&
strcmp (p, extension) == 0) {
- return g_strdup (name);
char *r = g_strdup (name);
char *rp = strrchr (r, '.');
*rp = '\0';
diff --git a/daemon/slave.c b/daemon/slave.c
index 2594e1da..c6eee3fc 100644
--- a/daemon/slave.c
+++ b/daemon/slave.c
@@ -106,11 +106,11 @@ static int greeter_fd_out = -1;
static int greeter_fd_in = -1;
typedef struct {
- int fd_r;
- int fd_w;
pid_t pid;
} GdmWaitPid;
+static int slave_waitpid_r = -1;
+static int slave_waitpid_w = -1;
static GSList *slave_waitpids = NULL;
extern gboolean gdm_first_login;
@@ -228,21 +228,16 @@ enum {
/* notify all waitpids, make waitpids check notifies */
static void
-slave_waitpid_notify_all (void)
+slave_waitpid_notify (void)
{
- GSList *li;
-
+ /* we're in no slave waitpids */
if (slave_waitpids == NULL)
return;
gdm_sigchld_block_push ();
- for (li = slave_waitpids; li != NULL; li = li->next) {
- GdmWaitPid *wp = li->data;
- if (wp->fd_w >= 0) {
- IGNORE_EINTR (write (wp->fd_w, "N", 1));
- }
- }
+ if (slave_waitpid_w >= 0)
+ IGNORE_EINTR (write (slave_waitpid_w, "N", 1));
gdm_sigchld_block_pop ();
}
@@ -260,14 +255,13 @@ slave_waitpid_setpid (pid_t pid)
wp = g_new0 (GdmWaitPid, 1);
wp->pid = pid;
- if G_UNLIKELY (pipe (p) < 0) {
- gdm_error ("slave_waitpid_setpid: cannot create pipe, trying to wing it");
-
- wp->fd_r = -1;
- wp->fd_w = -1;
- } else {
- wp->fd_r = p[0];
- wp->fd_w = p[1];
+ if (slave_waitpid_r < 0) {
+ if G_UNLIKELY (pipe (p) < 0) {
+ gdm_error ("slave_waitpid_setpid: cannot create pipe, trying to wing it");
+ } else {
+ slave_waitpid_r = p[0];
+ slave_waitpid_w = p[1];
+ }
}
slave_waitpids = g_slist_prepend (slave_waitpids, wp);
@@ -370,7 +364,7 @@ slave_waitpid (GdmWaitPid *wp)
gdm_debug ("slave_waitpid: waiting on %d", (int)wp->pid);
- if G_UNLIKELY (wp->fd_r < 0) {
+ if G_UNLIKELY (slave_waitpid_r < 0) {
gdm_error ("slave_waitpid: no pipe, trying to wing it");
/* This is a real stupid fallback for a real stupid case */
@@ -397,15 +391,15 @@ slave_waitpid (GdmWaitPid *wp)
int ret;
FD_ZERO (&rfds);
- FD_SET (wp->fd_r, &rfds);
+ FD_SET (slave_waitpid_r, &rfds);
if (read_session_output &&
d->session_output_fd >= 0)
FD_SET (d->session_output_fd, &rfds);
- ret = select (MAX (wp->fd_r, d->session_output_fd)+1, &rfds, NULL, NULL, NULL);
+ ret = select (MAX (slave_waitpid_r, d->session_output_fd)+1, &rfds, NULL, NULL, NULL);
if (ret > 0) {
- if (FD_ISSET (wp->fd_r, &rfds)) {
- IGNORE_EINTR (read (wp->fd_r, buf, 1));
+ if (FD_ISSET (slave_waitpid_r, &rfds)) {
+ IGNORE_EINTR (read (slave_waitpid_r, buf, 1));
}
if (d->session_output_fd >= 0 &&
FD_ISSET (d->session_output_fd, &rfds)) {
@@ -421,10 +415,6 @@ slave_waitpid (GdmWaitPid *wp)
gdm_sigchld_block_push ();
- IGNORE_EINTR (close (wp->fd_r));
- IGNORE_EINTR (close (wp->fd_w));
- wp->fd_r = -1;
- wp->fd_w = -1;
wp->pid = -1;
slave_waitpids = g_slist_remove (slave_waitpids, wp);
@@ -3510,6 +3500,9 @@ gdm_slave_session_start (void)
tmp = gdm_strip_extension (session, ".desktop");
g_free (session);
session = tmp;
+
+ gdm_debug ("Initial setting: session: '%s' language: '%s'\n",
+ session, language);
if (ve_string_empty (session)) {
g_free (session);
@@ -4011,8 +4004,8 @@ gdm_slave_child_handler (int sig)
GdmWaitPid *wp = li->data;
if (wp->pid == pid) {
wp->pid = -1;
- if (wp->fd_w >= 0) {
- IGNORE_EINTR (write (wp->fd_w, "!", 1));
+ if (slave_waitpid_w >= 0) {
+ IGNORE_EINTR (write (slave_waitpid_w, "!", 1));
}
}
}
@@ -4038,7 +4031,7 @@ gdm_slave_child_handler (int sig)
do_restart_greeter = TRUE;
if (restart_greeter_now) {
- slave_waitpid_notify_all ();
+ slave_waitpid_notify ();
} else {
interrupted = TRUE;
}
@@ -4146,7 +4139,7 @@ gdm_slave_handle_usr2_message (void)
else
gdm_ack_response = NULL;
} else if (s[0] == GDM_SLAVE_NOTIFY_KEY) {
- slave_waitpid_notify_all ();
+ slave_waitpid_notify ();
unhandled_notifies =
g_list_append (unhandled_notifies,
g_strdup (&s[1]));
diff --git a/docs/C/gdm.xml b/docs/C/gdm.xml
index dd760d40..d0c01b0b 100644
--- a/docs/C/gdm.xml
+++ b/docs/C/gdm.xml
@@ -2,8 +2,8 @@
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY legal SYSTEM "legal.xml">
- <!ENTITY version "2.4.4.0">
- <!ENTITY date "8/26/2003">
+ <!ENTITY version "2.4.4.1">
+ <!ENTITY date "9/12/2003">
]>
<article id="index" lang="en">
@@ -881,7 +881,7 @@
</para>
<para>
- Note that the PostSession script will be run even when the
+ Note that the <filename>PostSession</filename> script will be run even when the
display fails to respond due to an I/O error or similar. Thus,
there is no guarantee that X applications will work during
script execution.
@@ -894,7 +894,10 @@
so that you could perhaps use similar scripts for different display managers.
The <filename>Xsession</filename> will always have the
<filename>$GDMSESSION</filename> set to the basename of the
- session that the user chose to run.
+ session that the user chose to run without the <filename>.desktop</filename>
+ extension. In addition <filename>$DESKTOP_SESSION</filename> is also set
+ to the same value and in fact this will also be set by KDM in future
+ versions.
</para>
<para>
@@ -1042,7 +1045,8 @@
managers, and wish to have some of the script run only for GDM, then
you can check the presence of the <filename>GDMSESSION</filename>
environmental variable. This will always be set to the basename of
- <filename>.desktop</filename> file that is being used for this
+ <filename>.desktop</filename> (without the extension) file that is
+ being used for this
session, and will only be set for GDM sessions. Previously some
scripts were checking for <filename>GDM_LANG</filename>, but that
is only set when the user picks a non-system default language.