Showing error 913

User: Jiri Slaby
Error type: Double Lock
Error type description: Some lock is locked twice unintentionally in a sequence
File location: ipc/namespace.c
Line in file: 80
Project: Linux Kernel
Project version: 2.6.28
Tools: Undetermined 1
Entered: 2012-02-27 21:22:42 UTC


Source:

  1/*
  2 * linux/ipc/namespace.c
  3 * Copyright (C) 2006 Pavel Emelyanov <xemul@openvz.org> OpenVZ, SWsoft Inc.
  4 */
  5
  6#include <linux/ipc.h>
  7#include <linux/msg.h>
  8#include <linux/ipc_namespace.h>
  9#include <linux/rcupdate.h>
 10#include <linux/nsproxy.h>
 11#include <linux/slab.h>
 12
 13#include "util.h"
 14
 15static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns)
 16{
 17        struct ipc_namespace *ns;
 18
 19        ns = kmalloc(sizeof(struct ipc_namespace), GFP_KERNEL);
 20        if (ns == NULL)
 21                return ERR_PTR(-ENOMEM);
 22
 23        atomic_inc(&nr_ipc_ns);
 24
 25        sem_init_ns(ns);
 26        msg_init_ns(ns);
 27        shm_init_ns(ns);
 28
 29        /*
 30         * msgmni has already been computed for the new ipc ns.
 31         * Thus, do the ipcns creation notification before registering that
 32         * new ipcns in the chain.
 33         */
 34        ipcns_notify(IPCNS_CREATED);
 35        register_ipcns_notifier(ns);
 36
 37        kref_init(&ns->kref);
 38        return ns;
 39}
 40
 41struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns)
 42{
 43        struct ipc_namespace *new_ns;
 44
 45        BUG_ON(!ns);
 46        get_ipc_ns(ns);
 47
 48        if (!(flags & CLONE_NEWIPC))
 49                return ns;
 50
 51        new_ns = clone_ipc_ns(ns);
 52
 53        put_ipc_ns(ns);
 54        return new_ns;
 55}
 56
 57/*
 58 * free_ipcs - free all ipcs of one type
 59 * @ns:   the namespace to remove the ipcs from
 60 * @ids:  the table of ipcs to free
 61 * @free: the function called to free each individual ipc
 62 *
 63 * Called for each kind of ipc when an ipc_namespace exits.
 64 */
 65void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,
 66               void (*free)(struct ipc_namespace *, struct kern_ipc_perm *))
 67{
 68        struct kern_ipc_perm *perm;
 69        int next_id;
 70        int total, in_use;
 71
 72        down_write(&ids->rw_mutex);
 73
 74        in_use = ids->in_use;
 75
 76        for (total = 0, next_id = 0; total < in_use; next_id++) {
 77                perm = idr_find(&ids->ipcs_idr, next_id);
 78                if (perm == NULL)
 79                        continue;
 80                ipc_lock_by_ptr(perm);
 81                free(ns, perm);
 82                total++;
 83        }
 84        up_write(&ids->rw_mutex);
 85}
 86
 87void free_ipc_ns(struct kref *kref)
 88{
 89        struct ipc_namespace *ns;
 90
 91        ns = container_of(kref, struct ipc_namespace, kref);
 92        /*
 93         * Unregistering the hotplug notifier at the beginning guarantees
 94         * that the ipc namespace won't be freed while we are inside the
 95         * callback routine. Since the blocking_notifier_chain_XXX routines
 96         * hold a rw lock on the notifier list, unregister_ipcns_notifier()
 97         * won't take the rw lock before blocking_notifier_call_chain() has
 98         * released the rd lock.
 99         */
100        unregister_ipcns_notifier(ns);
101        sem_exit_ns(ns);
102        msg_exit_ns(ns);
103        shm_exit_ns(ns);
104        kfree(ns);
105        atomic_dec(&nr_ipc_ns);
106
107        /*
108         * Do the ipcns removal notification after decrementing nr_ipc_ns in
109         * order to have a correct value when recomputing msgmni.
110         */
111        ipcns_notify(IPCNS_REMOVED);
112}