summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/changelog2
-rw-r--r--debian/patches/auth-intr-cure.patch294
-rw-r--r--debian/patches/series1
3 files changed, 297 insertions, 0 deletions
diff --git a/debian/changelog b/debian/changelog
index bcc7c250..e096da97 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -15,6 +15,8 @@ hurd (20110227-1) UNRELEASED; urgency=low
(Closes: Bug#558664). Break old gnumach packages, instead of depending on
them. Break libc0.3 before getifaddrs fix, now that pfinet provides a
correct response.
+ * debian/patches/auth-intr-cure.patch: Add patch to mitigate
+ reauthentication issue triggered by sudo.
[ Justus Winter ]
* debian/hurd.{postinst,postrm}: Add/remove loginpr shell and login user with
diff --git a/debian/patches/auth-intr-cure.patch b/debian/patches/auth-intr-cure.patch
new file mode 100644
index 00000000..5ab007ba
--- /dev/null
+++ b/debian/patches/auth-intr-cure.patch
@@ -0,0 +1,294 @@
+See discussion starting at
+http://lists.gnu.org/archive/html/bug-hurd/2010-07/msg00010.html
+for the whole story. This is unfortunately not a complete patch, but mitigates
+the symptom.
+
+diff --git a/auth/auth.c b/auth/auth.c
+index 2afeaf7..11db0f8 100644
+--- a/auth/auth.c
++++ b/auth/auth.c
+@@ -251,11 +251,22 @@ S_auth_makeauth (struct authhandle *auth,
+
+ /* Transaction handling. */
+
+-/* A pending transaction. */
+-struct pending
++/* Since the user is responsible for freeing the rendezvous port, it has to
++ * wait for the server to have finished transmitting uids.
++ *
++ * The server thus waits for the user to give it uids (unless it was already
++ * there), transmits them and provides the passthrough port.
++ *
++ * The user gives the uids and waits for the passthrough port from the server.
++ *
++ * If the user is early, it has to tell the server it arrived.
++ */
++
++/* A pending user. */
++struct pending_user
+ {
+- hurd_ihash_locp_t locp; /* Position in one of the ihash tables. */
+- struct condition wakeup; /* The waiter is blocked on this condition. */
++ hurd_ihash_locp_t locp; /* Position in the pending_users ihash table. */
++ struct condition wakeup; /* The reader is blocked on this condition. */
+
+ /* The user's auth handle. */
+ struct authhandle *user;
+@@ -264,11 +275,18 @@ struct pending
+ mach_port_t passthrough;
+ };
+
++/* A pending server. */
++struct pending_server
++ {
++ hurd_ihash_locp_t locp; /* Position in the pending_servers ihash table. */
++ struct condition wakeup; /* The server is blocked on this condition. */
++ };
++
+ /* Table of pending transactions keyed on RENDEZVOUS. */
+ struct hurd_ihash pending_users
+- = HURD_IHASH_INITIALIZER (offsetof (struct pending, locp));
++ = HURD_IHASH_INITIALIZER (offsetof (struct pending_user, locp));
+ struct hurd_ihash pending_servers
+- = HURD_IHASH_INITIALIZER (offsetof (struct pending, locp));
++ = HURD_IHASH_INITIALIZER (offsetof (struct pending_server, locp));
+ struct mutex pending_lock = MUTEX_INITIALIZER;
+
+ /* Implement auth_user_authenticate as described in <hurd/auth.defs>. */
+@@ -280,7 +298,9 @@ S_auth_user_authenticate (struct authhandle *userauth,
+ mach_port_t *newport,
+ mach_msg_type_name_t *newporttype)
+ {
+- struct pending *s;
++ struct pending_server *s;
++ struct pending_user u;
++ error_t err;
+
+ if (! userauth)
+ return EOPNOTSUPP;
+@@ -288,65 +308,54 @@ S_auth_user_authenticate (struct authhandle *userauth,
+ if (rendezvous == MACH_PORT_DEAD) /* Port died in transit. */
+ return EINVAL;
+
++ u.user = userauth;
++ condition_init (&u.wakeup);
++
+ mutex_lock (&pending_lock);
+
+- /* Look for this port in the server list. */
+- s = hurd_ihash_find (&pending_servers, rendezvous);
+- if (s)
+- {
+- /* Found it! Extract the port. */
+- *newport = s->passthrough;
+- *newporttype = MACH_MSG_TYPE_MOVE_SEND;
++ err = hurd_ihash_add (&pending_users, rendezvous, &u);
++ if (err) {
++ mutex_unlock (&pending_lock);
++ return err;
++ }
+
+- /* Remove it from the pending list. */
+- hurd_ihash_locp_remove (&pending_servers, s->locp);
++ /* Give the server the auth port.
++ We need to add a ref in case the port dies. */
++ ports_port_ref (userauth);
+
+- /* Give the server the auth port and wake the RPC up.
+- We need to add a ref in case the port dies. */
+- s->user = userauth;
+- ports_port_ref (userauth);
++ /* Look for this rendezvous in the server list. */
++ s = hurd_ihash_find (&pending_servers, rendezvous);
++ if (s) {
++ /* Found it! */
+
+- condition_signal (&s->wakeup);
+- mutex_unlock (&pending_lock);
++ /* Remove it from the pending list. */
++ hurd_ihash_locp_remove (&pending_servers, s->locp);
+
+- mach_port_deallocate (mach_task_self (), rendezvous);
+- return 0;
+- }
+- else
++ /* Tell it we eventually arrived. */
++ condition_signal (&s->wakeup);
++ }
++
++ ports_interrupt_self_on_port_death (userauth, rendezvous);
++ /* Wait for server answer. */
++ if (hurd_condition_wait (&u.wakeup, &pending_lock) &&
++ hurd_ihash_find (&pending_users, rendezvous))
++ /* We were interrupted; remove our record. */
+ {
+- /* No pending server RPC for this port.
+- Create a pending user RPC record. */
+- struct pending u;
+- error_t err;
++ hurd_ihash_locp_remove (&pending_users, u.locp);
++ err = EINTR;
++ }
+
+- err = hurd_ihash_add (&pending_users, rendezvous, &u);
+- if (! err)
+- {
+- /* Store the user auth port and wait for the server RPC to wake
+- us up. */
+- u.user = userauth;
+- condition_init (&u.wakeup);
+- ports_interrupt_self_on_port_death (userauth, rendezvous);
+- if (hurd_condition_wait (&u.wakeup, &pending_lock)
+- && hurd_ihash_find (&pending_users, rendezvous))
+- /* We were interrupted; remove our record. */
+- {
+- hurd_ihash_locp_remove (&pending_users, u.locp);
+- err = EINTR;
+- }
+- }
+- /* The server side has already removed U from the ihash table. */
+- mutex_unlock (&pending_lock);
++ mutex_unlock (&pending_lock);
+
+- if (! err)
+- {
+- /* The server RPC has set the port and signalled U.wakeup. */
+- *newport = u.passthrough;
+- *newporttype = MACH_MSG_TYPE_MOVE_SEND;
+- mach_port_deallocate (mach_task_self (), rendezvous);
+- }
+- return err;
++ if (! err)
++ {
++ /* Extract the port. */
++ *newport = u.passthrough;
++ *newporttype = MACH_MSG_TYPE_MOVE_SEND;
++ mach_port_deallocate (mach_task_self (), rendezvous);
+ }
++
++ return err;
+ }
+
+ /* Implement auth_server_authenticate as described in <hurd/auth.defs>. */
+@@ -366,7 +375,7 @@ S_auth_server_authenticate (struct authhandle *serverauth,
+ uid_t **agids,
+ size_t *nagids)
+ {
+- struct pending *u;
++ struct pending_user *u;
+ struct authhandle *user;
+ error_t err;
+
+@@ -378,66 +387,69 @@ S_auth_server_authenticate (struct authhandle *serverauth,
+
+ mutex_lock (&pending_lock);
+
+- /* Look for this port in the user list. */
++ /* Look for this rendezvous in the user list. */
+ u = hurd_ihash_find (&pending_users, rendezvous);
+- if (u)
++ if (! u)
+ {
+- /* Remove it from the pending list. */
+- hurd_ihash_locp_remove (&pending_users, u->locp);
+-
+- /* Found it! We must add a ref because the one held by the
+- user RPC might die as soon as we unlock pending_lock. */
+- user = u->user;
+- ports_port_ref (user);
+-
+- /* Give the user the new port and wake the RPC up. */
+- u->passthrough = newport;
+-
+- condition_signal (&u->wakeup);
+- mutex_unlock (&pending_lock);
+- }
+- else
+- {
+- /* No pending user RPC for this port.
+- Create a pending server RPC record. */
+- struct pending s;
+-
++ /* User not here yet, have to wait for it. */
++ struct pending_server s;
++ condition_init (&s.wakeup);
+ err = hurd_ihash_add (&pending_servers, rendezvous, &s);
+ if (! err)
+- {
+- /* Store the new port and wait for the user RPC to wake us up. */
+- s.passthrough = newport;
+- condition_init (&s.wakeup);
++ {
+ ports_interrupt_self_on_port_death (serverauth, rendezvous);
+- if (hurd_condition_wait (&s.wakeup, &pending_lock)
+- && hurd_ihash_find (&pending_servers, rendezvous))
++ if (hurd_condition_wait (&s.wakeup, &pending_lock) &&
++ hurd_ihash_find (&pending_servers, rendezvous))
+ /* We were interrupted; remove our record. */
+ {
+ hurd_ihash_locp_remove (&pending_servers, s.locp);
+ err = EINTR;
+ }
+- }
+- /* The user side has already removed S from the ihash table. */
++ else
++ {
++ u = hurd_ihash_find (&pending_users, rendezvous);
++ if (! u)
++ /* User still not here, odd! */
++ err = EINTR;
++ }
++ }
++ }
++
++ if (u)
++ {
++ error_t err2;
++
++ /* Remove it from the pending list. */
++ hurd_ihash_locp_remove (&pending_users, u->locp);
++
++ /* Found it! */
++ user = u->user;
++
+ mutex_unlock (&pending_lock);
+
+- if (err)
+- return err;
++ /* Tell third party. */
++ err2 = auth_server_authenticate_reply (reply, reply_type, 0,
++ user->euids.ids, user->euids.num,
++ user->auids.ids, user->auids.num,
++ user->egids.ids, user->egids.num,
++ user->agids.ids, user->agids.num);
++
++ if (err2)
++ mach_port_deallocate (mach_task_self (), reply);
++
++ mutex_lock (&pending_lock);
++
++ /* Give the user the new port and wake the RPC up. */
++ u->passthrough = newport;
+
+- /* The user RPC has set the port (with a ref) and signalled S.wakeup. */
+- user = s.user;
++ condition_signal (&u->wakeup);
+ }
+
+- /* Extract the ids. We must use a separate reply stub so
+- we can deref the user auth handle after the reply uses its
+- contents. */
+- err = auth_server_authenticate_reply (reply, reply_type, 0,
+- user->euids.ids, user->euids.num,
+- user->auids.ids, user->auids.num,
+- user->egids.ids, user->egids.num,
+- user->agids.ids, user->agids.num);
++ mutex_unlock (&pending_lock);
+
+ if (err)
+- mach_port_deallocate (mach_task_self (), reply);
++ return err;
++
+ ports_port_deref (user);
+ mach_port_deallocate (mach_task_self (), rendezvous);
+ return MIG_NO_REPLY;
diff --git a/debian/patches/series b/debian/patches/series
index 08bebb4b..dffa9a24 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -28,3 +28,4 @@ console_ignore_bdf_err.patch
libpthread_sigmask.patch
disable-proc_getnports.patch
ext2fs_nowait.patch
+auth-intr-cure.patch