diff options
-rw-r--r-- | debian/changelog | 2 | ||||
-rw-r--r-- | debian/patches/auth-intr-cure.patch | 294 | ||||
-rw-r--r-- | debian/patches/series | 1 |
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 |