[haiku-commits] r41302 - in haiku/branches/developer/bonefish/signals: headers/private/kernel src/system/kernel

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 2 May 2011 15:39:23 +0200 (CEST)

Author: bonefish
Date: 2011-05-02 15:39:22 +0200 (Mon, 02 May 2011)
New Revision: 41302
Changeset: https://dev.haiku-os.org/changeset/41302

Modified:
   
haiku/branches/developer/bonefish/signals/headers/private/kernel/thread_types.h
   haiku/branches/developer/bonefish/signals/headers/private/kernel/usergroup.h
   haiku/branches/developer/bonefish/signals/src/system/kernel/team.cpp
   haiku/branches/developer/bonefish/signals/src/system/kernel/usergroup.cpp
Log:
* Team's user/group members are now protected by the object's lock instead of
  the global teams spinlock.
* Removed no longer needed inherit_parent_user_and_group_locked().
* _user_setgroups(): is_privileged() was called without any lock held
  (harmless).
* load_image_internal(): Fixed race condition: team should not be dereferenced
  after we create the main thread, since it might be killed by someone else from
  that point on.


Modified: 
haiku/branches/developer/bonefish/signals/headers/private/kernel/thread_types.h
===================================================================
--- 
haiku/branches/developer/bonefish/signals/headers/private/kernel/thread_types.h 
    2011-05-02 12:56:39 UTC (rev 41301)
+++ 
haiku/branches/developer/bonefish/signals/headers/private/kernel/thread_types.h 
    2011-05-02 13:39:22 UTC (rev 41302)
@@ -282,6 +282,7 @@
        bigtime_t               dead_threads_kernel_time;
        bigtime_t               dead_threads_user_time;
 
+       // user group information; protected by fLock
        uid_t                   saved_set_uid;
        uid_t                   real_uid;
        uid_t                   effective_uid;

Modified: 
haiku/branches/developer/bonefish/signals/headers/private/kernel/usergroup.h
===================================================================
--- 
haiku/branches/developer/bonefish/signals/headers/private/kernel/usergroup.h    
    2011-05-02 12:56:39 UTC (rev 41301)
+++ 
haiku/branches/developer/bonefish/signals/headers/private/kernel/usergroup.h    
    2011-05-02 13:39:22 UTC (rev 41302)
@@ -25,7 +25,6 @@
 // kernel private functions
 
 void           inherit_parent_user_and_group(Team* team, Team* parent);
-void           inherit_parent_user_and_group_locked(Team* team, Team* parent);
 status_t       update_set_id_user_and_group(Team* team, const char* file);
 
 // syscalls

Modified: haiku/branches/developer/bonefish/signals/src/system/kernel/team.cpp
===================================================================
--- haiku/branches/developer/bonefish/signals/src/system/kernel/team.cpp        
2011-05-02 12:56:39 UTC (rev 41301)
+++ haiku/branches/developer/bonefish/signals/src/system/kernel/team.cpp        
2011-05-02 13:39:22 UTC (rev 41302)
@@ -1346,7 +1346,6 @@
        port_id errorPort, uint32 errorToken)
 {
        char** flatArgs = _flatArgs;
-       Team* team;
        const char* threadName;
        thread_id thread;
        status_t status;
@@ -1354,6 +1353,7 @@
        struct team_arg* teamArgs;
        struct team_loading_info loadingInfo;
        io_context* parentIOContext = NULL;
+       team_id teamID;
 
        if (flatArgs == NULL || argCount == 0)
                return B_BAD_VALUE;
@@ -1363,9 +1363,10 @@
        TRACE(("load_image_internal: name '%s', args = %p, argCount = %ld\n",
                path, flatArgs, argCount));
 
-       team = Team::Create(path, false);
+       Team* team = Team::Create(path, false);
        if (team == NULL)
                return B_NO_MEMORY;
+       BReference<Team> teamReference(team, true);
 
        if (flags & B_WAIT_TILL_LOADED) {
                loadingInfo.thread = thread_get_current_thread();
@@ -1374,25 +1375,17 @@
                team->loading_info = &loadingInfo;
        }
 
-       InterruptsSpinLocker teamLocker(gTeamSpinlock);
-
        // get the parent team
-       Team* parent;
+       Team* parent = Team::Get(parentID);
+       if (parent == NULL)
+               return B_BAD_TEAM_ID;
+       BReference<Team> parentReference(parent, true);
 
-       if (parentID == B_CURRENT_TEAM)
-               parent = thread_get_current_thread()->team;
-       else
-               parent = team_get_team_struct_locked(parentID);
-
-       if (parent == NULL) {
-               teamLocker.Unlock();
-               status = B_BAD_TEAM_ID;
-               goto err0;
-       }
-
        // inherit the parent's user/group
-       inherit_parent_user_and_group_locked(team, parent);
+       inherit_parent_user_and_group(team, parent);
 
+       InterruptsSpinLocker teamLocker(gTeamSpinlock);
+
        sTeamHash.Insert(team);
        insert_team_into_parent(parent, team);
        insert_team_into_group(parent->group, team);
@@ -1450,15 +1443,23 @@
        // notify team listeners
        sNotificationService.Notify(TEAM_ADDED, team);
 
+       // In case we start the main thread, we shouldn't access the team object
+       // afterwards, so cache the team's ID.
+       teamID = team->id;
+
        // Create a kernel thread, but under the context of the new team
        // The new thread will take over ownership of teamArgs
        thread = spawn_kernel_thread_etc(team_create_thread_start, threadName,
-               B_NORMAL_PRIORITY, teamArgs, team->id, team->id);
+               B_NORMAL_PRIORITY, teamArgs, teamID, teamID);
        if (thread < 0) {
                status = thread;
                goto err5;
        }
 
+       // The team has been created successfully, so we keep the reference. Or
+       // more precisely: It's owned by the team's main thread, now.
+       teamReference.Detach();
+
        // wait for the loader of the new team to finish its work
        if ((flags & B_WAIT_TILL_LOADED) != 0) {
                Thread* mainThread;
@@ -1494,7 +1495,7 @@
        }
 
        // notify the debugger
-       user_debug_team_created(team->id);
+       user_debug_team_created(teamID);
 
        return thread;
 
@@ -1523,9 +1524,6 @@
        RELEASE_TEAM_LOCK();
        restore_interrupts(state);
 
-err0:
-       team->ReleaseReference();
-
        return status;
 }
 
@@ -1728,11 +1726,11 @@
 
        strlcpy(team->args, parentTeam->args, sizeof(team->args));
 
-       InterruptsSpinLocker teamLocker(gTeamSpinlock);
-
        // Inherit the parent's user/group.
-       inherit_parent_user_and_group_locked(team, parentTeam);
+       inherit_parent_user_and_group(team, parentTeam);
 
+       InterruptsSpinLocker teamLocker(gTeamSpinlock);
+
        sTeamHash.Insert(team);
        insert_team_into_parent(parentTeam, team);
        insert_team_into_group(parentTeam->group, team);
@@ -3930,14 +3928,15 @@
                io_context* ioContext;
                {
                        // get the team structure
-                       InterruptsSpinLocker _(gTeamSpinlock);
-                       Team* team = teamID == B_CURRENT_TEAM
-                               ? thread_get_current_thread()->team
-                               : team_get_team_struct_locked(teamID);
+                       Team* team = Team::Get(teamID);
                        if (team == NULL)
                                return B_BAD_TEAM_ID;
+                       BReference<Team> teamReference(team, true);
 
                        // copy the data
+                       TeamLocker teamLocker(team);
+                       InterruptsSpinLocker _(gTeamSpinlock);
+
                        teamClone->id = team->id;
                        strlcpy(teamClone->name, team->name, 
sizeof(teamClone->name));
                        teamClone->group_id = team->group_id;

Modified: 
haiku/branches/developer/bonefish/signals/src/system/kernel/usergroup.cpp
===================================================================
--- haiku/branches/developer/bonefish/signals/src/system/kernel/usergroup.cpp   
2011-05-02 12:56:39 UTC (rev 41301)
+++ haiku/branches/developer/bonefish/signals/src/system/kernel/usergroup.cpp   
2011-05-02 13:39:22 UTC (rev 41302)
@@ -3,6 +3,7 @@
  * Distributed under the terms of the MIT License.
  */
 
+
 #include <usergroup.h>
 
 #include <errno.h>
@@ -39,7 +40,7 @@
 {
        Team* team = thread_get_current_thread()->team;
 
-       InterruptsSpinLocker _(gTeamSpinlock);
+       TeamLocker teamLocker(team);
 
        bool privileged = kernel || is_privileged(team);
 
@@ -102,7 +103,7 @@
 {
        Team* team = thread_get_current_thread()->team;
 
-       InterruptsSpinLocker _(gTeamSpinlock);
+       TeamLocker teamLocker(team);
 
        bool privileged = kernel || is_privileged(team);
 
@@ -165,7 +166,7 @@
 {
        Team* team = thread_get_current_thread()->team;
 
-       InterruptsSpinLocker _(gTeamSpinlock);
+       TeamLocker teamLocker(team);
 
        const gid_t* groups = team->supplementary_groups;
        int actualCount = team->supplementary_group_count;
@@ -223,15 +224,15 @@
                }
        }
 
-       InterruptsSpinLocker locker(gTeamSpinlock);
-
        Team* team = thread_get_current_thread()->team;
 
+       TeamLocker teamLocker(team);
+
        gid_t* toFree = team->supplementary_groups;
        team->supplementary_groups = newGroups;
        team->supplementary_group_count = groupCount;
 
-       locker.Unlock();
+       teamLocker.Unlock();
 
        malloc_referenced_release(toFree);
 
@@ -243,8 +244,11 @@
 
 
 void
-inherit_parent_user_and_group_locked(Team* team, Team* parent)
+inherit_parent_user_and_group(Team* team, Team* parent)
 {
+       TeamLocker parentLocker(parent);
+       TeamLocker teamLocker(team);
+
        team->saved_set_uid = parent->saved_set_uid;
        team->real_uid = parent->real_uid;
        team->effective_uid = parent->effective_uid;
@@ -258,14 +262,6 @@
 }
 
 
-void
-inherit_parent_user_and_group(Team* team, Team* parent)
-{
-       InterruptsSpinLocker _(gTeamSpinlock);
-       inherit_parent_user_and_group_locked(team, parent);
-}
-
-
 status_t
 update_set_id_user_and_group(Team* team, const char* file)
 {
@@ -274,7 +270,7 @@
        if (status != B_OK)
                return status;
 
-       InterruptsSpinLocker _(gTeamSpinlock);
+       TeamLocker teamLocker(team);
 
        if ((st.st_mode & S_ISUID) != 0) {
                team->saved_set_uid = st.st_uid;
@@ -381,8 +377,13 @@
 ssize_t
 _user_setgroups(int groupCount, const gid_t* groupList)
 {
-       if (!is_privileged(thread_get_current_thread()->team))
-               return EPERM;
+       // check privilege
+       {
+               Team* team = thread_get_current_thread()->team;
+               TeamLocker teamLocker(team);
+               if (!is_privileged(team))
+                       return EPERM;
+       }
 
        return common_setgroups(groupCount, groupList, false);
 }


Other related posts:

  • » [haiku-commits] r41302 - in haiku/branches/developer/bonefish/signals: headers/private/kernel src/system/kernel - ingo_weinhold