Showing error 1525

User: Jiri Slaby
Error type: Leaving function in locked state
Error type description: Some lock is not unlocked on all paths of a function, so it is leaked
File location: net/netfilter/nf_log.c
Line in file: 107
Project: Linux Kernel
Project version: 2.6.28
Tools: Stanse (1.2)
Entered: 2012-05-21 20:30:05 UTC


Source:

  1#include <linux/kernel.h>
  2#include <linux/init.h>
  3#include <linux/module.h>
  4#include <linux/proc_fs.h>
  5#include <linux/skbuff.h>
  6#include <linux/netfilter.h>
  7#include <linux/seq_file.h>
  8#include <net/protocol.h>
  9#include <net/netfilter/nf_log.h>
 10
 11#include "nf_internals.h"
 12
 13/* Internal logging interface, which relies on the real
 14   LOG target modules */
 15
 16#define NF_LOG_PREFIXLEN                128
 17
 18static const struct nf_logger *nf_loggers[NFPROTO_NUMPROTO] __read_mostly;
 19static DEFINE_MUTEX(nf_log_mutex);
 20
 21/* return EBUSY if somebody else is registered, EEXIST if the same logger
 22 * is registred, 0 on success. */
 23int nf_log_register(u_int8_t pf, const struct nf_logger *logger)
 24{
 25        int ret;
 26
 27        if (pf >= ARRAY_SIZE(nf_loggers))
 28                return -EINVAL;
 29
 30        /* Any setup of logging members must be done before
 31         * substituting pointer. */
 32        ret = mutex_lock_interruptible(&nf_log_mutex);
 33        if (ret < 0)
 34                return ret;
 35
 36        if (!nf_loggers[pf])
 37                rcu_assign_pointer(nf_loggers[pf], logger);
 38        else if (nf_loggers[pf] == logger)
 39                ret = -EEXIST;
 40        else
 41                ret = -EBUSY;
 42
 43        mutex_unlock(&nf_log_mutex);
 44        return ret;
 45}
 46EXPORT_SYMBOL(nf_log_register);
 47
 48void nf_log_unregister_pf(u_int8_t pf)
 49{
 50        if (pf >= ARRAY_SIZE(nf_loggers))
 51                return;
 52        mutex_lock(&nf_log_mutex);
 53        rcu_assign_pointer(nf_loggers[pf], NULL);
 54        mutex_unlock(&nf_log_mutex);
 55
 56        /* Give time to concurrent readers. */
 57        synchronize_rcu();
 58}
 59EXPORT_SYMBOL(nf_log_unregister_pf);
 60
 61void nf_log_unregister(const struct nf_logger *logger)
 62{
 63        int i;
 64
 65        mutex_lock(&nf_log_mutex);
 66        for (i = 0; i < ARRAY_SIZE(nf_loggers); i++) {
 67                if (nf_loggers[i] == logger)
 68                        rcu_assign_pointer(nf_loggers[i], NULL);
 69        }
 70        mutex_unlock(&nf_log_mutex);
 71
 72        synchronize_rcu();
 73}
 74EXPORT_SYMBOL(nf_log_unregister);
 75
 76void nf_log_packet(u_int8_t pf,
 77                   unsigned int hooknum,
 78                   const struct sk_buff *skb,
 79                   const struct net_device *in,
 80                   const struct net_device *out,
 81                   const struct nf_loginfo *loginfo,
 82                   const char *fmt, ...)
 83{
 84        va_list args;
 85        char prefix[NF_LOG_PREFIXLEN];
 86        const struct nf_logger *logger;
 87
 88        rcu_read_lock();
 89        logger = rcu_dereference(nf_loggers[pf]);
 90        if (logger) {
 91                va_start(args, fmt);
 92                vsnprintf(prefix, sizeof(prefix), fmt, args);
 93                va_end(args);
 94                logger->logfn(pf, hooknum, skb, in, out, loginfo, prefix);
 95        }
 96        rcu_read_unlock();
 97}
 98EXPORT_SYMBOL(nf_log_packet);
 99
100#ifdef CONFIG_PROC_FS
101static void *seq_start(struct seq_file *seq, loff_t *pos)
102        __acquires(RCU)
103{
104        rcu_read_lock();
105
106        if (*pos >= ARRAY_SIZE(nf_loggers))
107                return NULL;
108
109        return pos;
110}
111
112static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
113{
114        (*pos)++;
115
116        if (*pos >= ARRAY_SIZE(nf_loggers))
117                return NULL;
118
119        return pos;
120}
121
122static void seq_stop(struct seq_file *s, void *v)
123        __releases(RCU)
124{
125        rcu_read_unlock();
126}
127
128static int seq_show(struct seq_file *s, void *v)
129{
130        loff_t *pos = v;
131        const struct nf_logger *logger;
132
133        logger = rcu_dereference(nf_loggers[*pos]);
134
135        if (!logger)
136                return seq_printf(s, "%2lld NONE\n", *pos);
137
138        return seq_printf(s, "%2lld %s\n", *pos, logger->name);
139}
140
141static const struct seq_operations nflog_seq_ops = {
142        .start        = seq_start,
143        .next        = seq_next,
144        .stop        = seq_stop,
145        .show        = seq_show,
146};
147
148static int nflog_open(struct inode *inode, struct file *file)
149{
150        return seq_open(file, &nflog_seq_ops);
151}
152
153static const struct file_operations nflog_file_ops = {
154        .owner         = THIS_MODULE,
155        .open         = nflog_open,
156        .read         = seq_read,
157        .llseek         = seq_lseek,
158        .release = seq_release,
159};
160
161#endif /* PROC_FS */
162
163
164int __init netfilter_log_init(void)
165{
166#ifdef CONFIG_PROC_FS
167        if (!proc_create("nf_log", S_IRUGO,
168                         proc_net_netfilter, &nflog_file_ops))
169                return -1;
170#endif
171        return 0;
172}