Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=b1ed88b47f5e18c6efb8041275c16eeead5377df
Commit:     b1ed88b47f5e18c6efb8041275c16eeead5377df
Parent:     15aafa2f9d8399b22e418c53a87dfc0c43f4030f
Author:     Pierre Peiffer <[EMAIL PROTECTED]>
AuthorDate: Wed Feb 6 01:36:23 2008 -0800
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Wed Feb 6 10:41:01 2008 -0800

    IPC: fix error check in all new xxx_lock() and xxx_exit_ns() functions
    
    In the new implementation of the [sem|shm|msg]_lock[_check]() routines, we
    use the return value of ipc_lock() in container_of() without any check.
    But ipc_lock may return a errcode.  The use of this errcode in
    container_of() may alter this errcode, and we don't want this.
    
    And in xxx_exit_ns, the pointer return by idr_find is of type 'struct
    kern_ipc_per'...
    
    Today, the code will work as is because the member used in these
    container_of() is the first member of its container (offset == 0), the
    errcode isn't changed then.  But in the general case, we can't count on
    this assumption and this may lead later to a real bug if we don't correct
    this.
    
    Again, the proposed solution is simple and correct.  But, as pointed by
    Nadia, with this solution, the same check will be done several times (in
    all sub-callers...), what is not very funny/optimal...
    
    Signed-off-by: Pierre Peiffer <[EMAIL PROTECTED]>
    Cc: Nadia Derbey <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 ipc/msg.c |   17 ++++++++++++++---
 ipc/sem.c |   17 ++++++++++++++---
 ipc/shm.c |   20 +++++++++++++++++---
 3 files changed, 45 insertions(+), 9 deletions(-)

diff --git a/ipc/msg.c b/ipc/msg.c
index fdf3db5..ec0c724 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -105,6 +105,7 @@ int msg_init_ns(struct ipc_namespace *ns)
 void msg_exit_ns(struct ipc_namespace *ns)
 {
        struct msg_queue *msq;
+       struct kern_ipc_perm *perm;
        int next_id;
        int total, in_use;
 
@@ -113,10 +114,11 @@ void msg_exit_ns(struct ipc_namespace *ns)
        in_use = msg_ids(ns).in_use;
 
        for (total = 0, next_id = 0; total < in_use; next_id++) {
-               msq = idr_find(&msg_ids(ns).ipcs_idr, next_id);
-               if (msq == NULL)
+               perm = idr_find(&msg_ids(ns).ipcs_idr, next_id);
+               if (perm == NULL)
                        continue;
-               ipc_lock_by_ptr(&msq->q_perm);
+               ipc_lock_by_ptr(perm);
+               msq = container_of(perm, struct msg_queue, q_perm);
                freeque(ns, msq);
                total++;
        }
@@ -144,6 +146,9 @@ static inline struct msg_queue *msg_lock_check_down(struct 
ipc_namespace *ns,
 {
        struct kern_ipc_perm *ipcp = ipc_lock_check_down(&msg_ids(ns), id);
 
+       if (IS_ERR(ipcp))
+               return (struct msg_queue *)ipcp;
+
        return container_of(ipcp, struct msg_queue, q_perm);
 }
 
@@ -155,6 +160,9 @@ static inline struct msg_queue *msg_lock(struct 
ipc_namespace *ns, int id)
 {
        struct kern_ipc_perm *ipcp = ipc_lock(&msg_ids(ns), id);
 
+       if (IS_ERR(ipcp))
+               return (struct msg_queue *)ipcp;
+
        return container_of(ipcp, struct msg_queue, q_perm);
 }
 
@@ -163,6 +171,9 @@ static inline struct msg_queue *msg_lock_check(struct 
ipc_namespace *ns,
 {
        struct kern_ipc_perm *ipcp = ipc_lock_check(&msg_ids(ns), id);
 
+       if (IS_ERR(ipcp))
+               return (struct msg_queue *)ipcp;
+
        return container_of(ipcp, struct msg_queue, q_perm);
 }
 
diff --git a/ipc/sem.c b/ipc/sem.c
index 35952c0..d65e285 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -143,6 +143,7 @@ int sem_init_ns(struct ipc_namespace *ns)
 void sem_exit_ns(struct ipc_namespace *ns)
 {
        struct sem_array *sma;
+       struct kern_ipc_perm *perm;
        int next_id;
        int total, in_use;
 
@@ -151,10 +152,11 @@ void sem_exit_ns(struct ipc_namespace *ns)
        in_use = sem_ids(ns).in_use;
 
        for (total = 0, next_id = 0; total < in_use; next_id++) {
-               sma = idr_find(&sem_ids(ns).ipcs_idr, next_id);
-               if (sma == NULL)
+               perm = idr_find(&sem_ids(ns).ipcs_idr, next_id);
+               if (perm == NULL)
                        continue;
-               ipc_lock_by_ptr(&sma->sem_perm);
+               ipc_lock_by_ptr(perm);
+               sma = container_of(perm, struct sem_array, sem_perm);
                freeary(ns, sma);
                total++;
        }
@@ -181,6 +183,9 @@ static inline struct sem_array *sem_lock_check_down(struct 
ipc_namespace *ns,
 {
        struct kern_ipc_perm *ipcp = ipc_lock_check_down(&sem_ids(ns), id);
 
+       if (IS_ERR(ipcp))
+               return (struct sem_array *)ipcp;
+
        return container_of(ipcp, struct sem_array, sem_perm);
 }
 
@@ -192,6 +197,9 @@ static inline struct sem_array *sem_lock(struct 
ipc_namespace *ns, int id)
 {
        struct kern_ipc_perm *ipcp = ipc_lock(&sem_ids(ns), id);
 
+       if (IS_ERR(ipcp))
+               return (struct sem_array *)ipcp;
+
        return container_of(ipcp, struct sem_array, sem_perm);
 }
 
@@ -200,6 +208,9 @@ static inline struct sem_array *sem_lock_check(struct 
ipc_namespace *ns,
 {
        struct kern_ipc_perm *ipcp = ipc_lock_check(&sem_ids(ns), id);
 
+       if (IS_ERR(ipcp))
+               return (struct sem_array *)ipcp;
+
        return container_of(ipcp, struct sem_array, sem_perm);
 }
 
diff --git a/ipc/shm.c b/ipc/shm.c
index 3818fae..65c3a29 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -111,6 +111,7 @@ int shm_init_ns(struct ipc_namespace *ns)
 void shm_exit_ns(struct ipc_namespace *ns)
 {
        struct shmid_kernel *shp;
+       struct kern_ipc_perm *perm;
        int next_id;
        int total, in_use;
 
@@ -119,10 +120,11 @@ void shm_exit_ns(struct ipc_namespace *ns)
        in_use = shm_ids(ns).in_use;
 
        for (total = 0, next_id = 0; total < in_use; next_id++) {
-               shp = idr_find(&shm_ids(ns).ipcs_idr, next_id);
-               if (shp == NULL)
+               perm = idr_find(&shm_ids(ns).ipcs_idr, next_id);
+               if (perm == NULL)
                        continue;
-               ipc_lock_by_ptr(&shp->shm_perm);
+               ipc_lock_by_ptr(perm);
+               shp = container_of(perm, struct shmid_kernel, shm_perm);
                do_shm_rmid(ns, shp);
                total++;
        }
@@ -149,6 +151,9 @@ static inline struct shmid_kernel *shm_lock_down(struct 
ipc_namespace *ns,
 {
        struct kern_ipc_perm *ipcp = ipc_lock_down(&shm_ids(ns), id);
 
+       if (IS_ERR(ipcp))
+               return (struct shmid_kernel *)ipcp;
+
        return container_of(ipcp, struct shmid_kernel, shm_perm);
 }
 
@@ -158,6 +163,9 @@ static inline struct shmid_kernel *shm_lock_check_down(
 {
        struct kern_ipc_perm *ipcp = ipc_lock_check_down(&shm_ids(ns), id);
 
+       if (IS_ERR(ipcp))
+               return (struct shmid_kernel *)ipcp;
+
        return container_of(ipcp, struct shmid_kernel, shm_perm);
 }
 
@@ -169,6 +177,9 @@ static inline struct shmid_kernel *shm_lock(struct 
ipc_namespace *ns, int id)
 {
        struct kern_ipc_perm *ipcp = ipc_lock(&shm_ids(ns), id);
 
+       if (IS_ERR(ipcp))
+               return (struct shmid_kernel *)ipcp;
+
        return container_of(ipcp, struct shmid_kernel, shm_perm);
 }
 
@@ -177,6 +188,9 @@ static inline struct shmid_kernel *shm_lock_check(struct 
ipc_namespace *ns,
 {
        struct kern_ipc_perm *ipcp = ipc_lock_check(&shm_ids(ns), id);
 
+       if (IS_ERR(ipcp))
+               return (struct shmid_kernel *)ipcp;
+
        return container_of(ipcp, struct shmid_kernel, shm_perm);
 }
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to