Author: bonefish Date: 2011-05-24 18:47:30 +0200 (Tue, 24 May 2011) New Revision: 41714 Changeset: https://dev.haiku-os.org/changeset/41714 Modified: haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp Log: deliver_signal_locked(), send_signal_to_team_locked(): Added permission checks. Modified: haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp =================================================================== --- haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp 2011-05-24 16:45:01 UTC (rev 41713) +++ haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp 2011-05-24 16:47:30 UTC (rev 41714) @@ -1260,6 +1260,29 @@ } +/*! Checks whether the current user has permission to send a signal to the given + target team. + + The caller must hold the scheduler lock or \a team's lock. + + \param team The target team. + \param schedulerLocked \c true, if the caller holds the scheduler lock, + \c false otherwise. +*/ +static bool +has_permission_to_signal(Team* team, bool schedulerLocked) +{ + // get the current user + uid_t currentUser = schedulerLocked + ? thread_get_current_thread()->team->effective_uid + : geteuid(); + + // root is omnipotent -- in the other cases the current user must match the + // target team's + return currentUser == 0 || currentUser == team->effective_uid; +} + + /*! Delivers the \a signal to the \a thread, but doesn't handle the signal -- it just makes sure the thread gets the signal, i.e. unblocks it if needed. @@ -1286,7 +1309,8 @@ BReference<Signal> signalReference(signal, true); if ((flags & B_CHECK_PERMISSION) != 0) { - // TODO: check permission + if (!has_permission_to_signal(thread->team, true)) + return EPERM; } if (signalNumber == 0) @@ -1447,15 +1471,16 @@ T(SendSignal(team->id, signal.Number(), flags)); if ((flags & B_CHECK_PERMISSION) != 0) { - // TODO: check permission + if (!has_permission_to_signal(team, false)) + return EPERM; } if (signal.Number() == 0) return B_OK; if (team == team_get_kernel_team()) { - // signals to the kernel team are ignored - return B_NOT_ALLOWED; + // signals to the kernel team are not allowed + return EPERM; } // Clone the signal -- the clone will be queued. If something fails and the @@ -1596,9 +1621,19 @@ { T(SendSignal(-group->id, signal.Number(), flags)); + bool firstTeam = true; + for (Team* team = group->teams; team != NULL; team = team->group_next) { TeamLocker teamLocker(team); - send_signal_to_team_locked(team, signal, flags | B_DO_NOT_RESCHEDULE); + status_t error = send_signal_to_team_locked(team, signal, + flags | B_DO_NOT_RESCHEDULE); + // If sending to the first team in the group failed, let the whole call + // fail. + if (firstTeam) { + if (error != B_OK) + return error; + firstTeam = false; + } } if ((flags & B_DO_NOT_RESCHEDULE) == 0)