Guest User

Treviño - kdbus openmoko 2.6.32 kernel support

a guest
Sep 24th, 2010
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 190.49 KB | None | 0 0
  1. diff --git a/include/linux/security.h b/include/linux/security.h
  2. index 0c88191..e1fcd9f 100644
  3. --- a/include/linux/security.h
  4. +++ b/include/linux/security.h
  5. @@ -1563,7 +1563,10 @@ struct security_operations {
  6.  #ifdef CONFIG_SECURITY_NETWORK
  7.         int (*unix_stream_connect) (struct socket *sock,
  8.                                     struct socket *other, struct sock *newsk);
  9. +       int (*dbus_stream_connect) (struct socket *sock,
  10. +                                   struct socket *other, struct sock *newsk);
  11.         int (*unix_may_send) (struct socket *sock, struct socket *other);
  12. +       int (*dbus_may_send) (struct socket *sock, struct socket *other);
  13.  
  14.         int (*socket_create) (int family, int type, int protocol, int kern);
  15.         int (*socket_post_create) (struct socket *sock, int family,
  16. @@ -2518,7 +2521,10 @@ static inline int security_inode_getsecctx(struct inode *inode, void **ctx, u32
  17.  
  18.  int security_unix_stream_connect(struct socket *sock, struct socket *other,
  19.                                  struct sock *newsk);
  20. +int security_dbus_stream_connect(struct socket *sock, struct socket *other,
  21. +                                struct sock *newsk);
  22.  int security_unix_may_send(struct socket *sock,  struct socket *other);
  23. +int security_dbus_may_send(struct socket *sock,  struct socket *other);
  24.  int security_socket_create(int family, int type, int protocol, int kern);
  25.  int security_socket_post_create(struct socket *sock, int family,
  26.                                 int type, int protocol, int kern);
  27. @@ -2562,12 +2568,25 @@ static inline int security_unix_stream_connect(struct socket *sock,
  28.         return 0;
  29.  }
  30.  
  31. +static inline int security_dbus_stream_connect(struct socket *sock,
  32. +                                              struct socket *other,
  33. +                                              struct sock *newsk)
  34. +{
  35. +       return 0;
  36. +}
  37. +
  38.  static inline int security_unix_may_send(struct socket *sock,
  39.                                          struct socket *other)
  40.  {
  41.         return 0;
  42.  }
  43.  
  44. +static inline int security_dbus_may_send(struct socket *sock,
  45. +                                        struct socket *other)
  46. +{
  47. +       return 0;
  48. +}
  49. +
  50.  static inline int security_socket_create(int family, int type,
  51.                                          int protocol, int kern)
  52.  {
  53. diff --git a/include/linux/socket.h b/include/linux/socket.h
  54. index 032a19e..ae8e296 100644
  55. --- a/include/linux/socket.h
  56. +++ b/include/linux/socket.h
  57. @@ -180,7 +180,8 @@
  58.  #define AF_ISDN                34      /* mISDN sockets                */
  59.  #define AF_PHONET      35      /* Phonet sockets               */
  60.  #define AF_IEEE802154  36      /* IEEE802154 sockets           */
  61. -#define AF_MAX         37      /* For now.. */
  62. +#define AF_DBUS                37      /* DBUS sockets                 */
  63. +#define AF_MAX         38      /* For now.. */
  64.  
  65.  /* Protocol families, same as address families. */
  66.  #define PF_UNSPEC      AF_UNSPEC
  67. @@ -220,6 +221,7 @@
  68.  #define PF_ISDN                AF_ISDN
  69.  #define PF_PHONET      AF_PHONET
  70.  #define PF_IEEE802154  AF_IEEE802154
  71. +#define PF_DBUS                AF_DBUS
  72.  #define PF_MAX         AF_MAX
  73.  
  74.  /* Maximum queue length specifiable by listen.  */
  75. diff --git a/include/net/af_dbus.h b/include/net/af_dbus.h
  76. new file mode 100644
  77. index 0000000..0d05784
  78. --- /dev/null
  79. +++ b/include/net/af_dbus.h
  80. @@ -0,0 +1,85 @@
  81. +#ifndef __LINUX_NET_AFDBUS_H
  82. +#define __LINUX_NET_AFDBUS_H
  83. +
  84. +#include <linux/socket.h>
  85. +#include <linux/un.h>
  86. +#include <linux/mutex.h>
  87. +#include <net/sock.h>
  88. +
  89. +extern void dbus_inflight(struct file *fp);
  90. +extern void dbus_notinflight(struct file *fp);
  91. +extern void dbus_gc(void);
  92. +extern void wait_for_dbus_gc(void);
  93. +
  94. +#define DBUS_HASH_SIZE 256
  95. +
  96. +extern unsigned int dbus_tot_inflight;
  97. +
  98. +struct dbus_address {
  99. +       atomic_t        refcnt;
  100. +       int             len;
  101. +       unsigned        hash;
  102. +       struct sockaddr_un name[0];
  103. +};
  104. +
  105. +struct dbus_skb_parms {
  106. +       struct ucred            creds;          /* Skb credentials      */
  107. +       struct scm_fp_list      *fp;            /* Passed files         */
  108. +#ifdef CONFIG_SECURITY_NETWORK
  109. +       u32                     secid;          /* Security ID          */
  110. +#endif
  111. +};
  112. +
  113. +#define DBUSCB(skb)    (*(struct dbus_skb_parms *)&((skb)->cb))
  114. +#define DBUSCREDS(skb) (&DBUSCB((skb)).creds)
  115. +#define DBUSSID(skb)   (&DBUSCB((skb)).secid)
  116. +
  117. +#define dbus_state_lock(s)     spin_lock(&dbus_sk(s)->lock)
  118. +#define dbus_state_unlock(s)   spin_unlock(&dbus_sk(s)->lock)
  119. +#define dbus_state_lock_nested(s) \
  120. +                               spin_lock_nested(&dbus_sk(s)->lock, \
  121. +                               SINGLE_DEPTH_NESTING)
  122. +
  123. +#ifdef __KERNEL__
  124. +/* The AF_DBUS socket */
  125. +struct dbus_sock_priv;
  126. +struct DBusBus;
  127. +struct dbus_sock {
  128. +       /* WARNING: sk has to be the first member */
  129. +       struct sock             sk;
  130. +       struct dbus_address     *addr;
  131. +       struct dentry           *dentry;
  132. +       struct vfsmount         *mnt;
  133. +       struct mutex            readlock;
  134. +       struct sock             *peer;
  135. +       struct sock             *other;
  136. +       struct list_head        link;
  137. +       atomic_long_t           inflight;
  138. +       spinlock_t              lock;
  139. +       unsigned int            gc_candidate : 1;
  140. +       unsigned int            gc_maybe_cycle : 1;
  141. +       struct socket_wq        peer_wq;
  142. +
  143. +       struct dbus_sock_priv   *priv;
  144. +       unsigned int    daemon_side;
  145. +       unsigned int    authenticated;
  146. +       char            *uniq_name;
  147. +#define MAX_WELL_KNOWN_NAMES 10
  148. +       char            *well_known_names[MAX_WELL_KNOWN_NAMES];
  149. +       struct DBusBus  *bus;
  150. +       struct hlist_node       bus_link;
  151. +
  152. +};
  153. +#define dbus_sk(__sk) ((struct dbus_sock *)__sk)
  154. +
  155. +#define peer_wait peer_wq.wait
  156. +
  157. +#ifdef CONFIG_SYSCTL
  158. +extern int dbus_sysctl_register(struct net *net);
  159. +extern void dbus_sysctl_unregister(struct net *net);
  160. +#else
  161. +static inline int dbus_sysctl_register(struct net *net) { return 0; }
  162. +static inline void dbus_sysctl_unregister(struct net *net) {}
  163. +#endif
  164. +#endif
  165. +#endif
  166. diff --git a/net/Kconfig b/net/Kconfig
  167. index 0d68b40..2a7f72d 100644
  168. --- a/net/Kconfig
  169. +++ b/net/Kconfig
  170. @@ -47,6 +47,7 @@ menu "Networking options"
  171.  
  172.  source "net/packet/Kconfig"
  173.  source "net/unix/Kconfig"
  174. +source "net/dbus/Kconfig"
  175.  source "net/xfrm/Kconfig"
  176.  source "net/iucv/Kconfig"
  177.  
  178. diff --git a/net/Makefile b/net/Makefile
  179. index cb7bdc1..bb9fa24 100644
  180. --- a/net/Makefile
  181. +++ b/net/Makefile
  182. @@ -19,6 +19,7 @@ obj-$(CONFIG_NETFILTER)               += netfilter/
  183.  obj-$(CONFIG_INET)             += ipv4/
  184.  obj-$(CONFIG_XFRM)             += xfrm/
  185.  obj-$(CONFIG_UNIX)             += unix/
  186. +obj-$(CONFIG_DBUS)             += dbus/
  187.  ifneq ($(CONFIG_IPV6),)
  188.  obj-y                          += ipv6/
  189.  endif
  190. diff --git a/net/core/sock.c b/net/core/sock.c
  191. index 2cf7f9f..cc96185 100644
  192. --- a/net/core/sock.c
  193. +++ b/net/core/sock.c
  194. @@ -156,7 +156,7 @@ static const char *const af_family_key_strings[AF_MAX+1] = {
  195.    "sk_lock-27"       , "sk_lock-28"          , "sk_lock-AF_CAN"      ,
  196.    "sk_lock-AF_TIPC"  , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV"        ,
  197.    "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN"     , "sk_lock-AF_PHONET"   ,
  198. -  "sk_lock-AF_IEEE802154",
  199. +  "sk_lock-AF_IEEE802154", "sk_lock-AF_DBUS",
  200.    "sk_lock-AF_MAX"
  201.  };
  202.  static const char *const af_family_slock_key_strings[AF_MAX+1] = {
  203. @@ -172,7 +172,7 @@ static const char *const af_family_slock_key_strings[AF_MAX+1] = {
  204.    "slock-27"       , "slock-28"          , "slock-AF_CAN"      ,
  205.    "slock-AF_TIPC"  , "slock-AF_BLUETOOTH", "slock-AF_IUCV"     ,
  206.    "slock-AF_RXRPC" , "slock-AF_ISDN"     , "slock-AF_PHONET"   ,
  207. -  "slock-AF_IEEE802154",
  208. +  "slock-AF_IEEE802154", "slock-AF_DBUS",
  209.    "slock-AF_MAX"
  210.  };
  211.  static const char *const af_family_clock_key_strings[AF_MAX+1] = {
  212. @@ -188,7 +188,7 @@ static const char *const af_family_clock_key_strings[AF_MAX+1] = {
  213.    "clock-27"       , "clock-28"          , "clock-AF_CAN"      ,
  214.    "clock-AF_TIPC"  , "clock-AF_BLUETOOTH", "clock-AF_IUCV"     ,
  215.    "clock-AF_RXRPC" , "clock-AF_ISDN"     , "clock-AF_PHONET"   ,
  216. -  "clock-AF_IEEE802154",
  217. +  "clock-AF_IEEE802154", "clock-AF_DBUS",
  218.    "clock-AF_MAX"
  219.  };
  220.  
  221. diff --git a/net/dbus/Kconfig b/net/dbus/Kconfig
  222. new file mode 100644
  223. index 0000000..04a759a
  224. --- /dev/null
  225. +++ b/net/dbus/Kconfig
  226. @@ -0,0 +1,16 @@
  227. +#
  228. +# D-Bus Domain Sockets
  229. +#
  230. +
  231. +config DBUS
  232. +       tristate "DBUS domain sockets (EXPERIMENTAL)"
  233. +       depends on EXPERIMENTAL
  234. +       ---help---
  235. +         If you say Y here, you will include support for D-BUS domain sockets.
  236. +         D-BUS sockets are similar to Unix sockets but with D-Bus routing in
  237. +         order to provide better performances than the traditional
  238. +         dbus-daemon.
  239. +
  240. +         To compile this driver as a module, choose M here: the
  241. +         module will be called dbus.  If unsure, say N.
  242. +
  243. diff --git a/net/dbus/Makefile b/net/dbus/Makefile
  244. new file mode 100644
  245. index 0000000..8df236c
  246. --- /dev/null
  247. +++ b/net/dbus/Makefile
  248. @@ -0,0 +1,8 @@
  249. +#
  250. +# Makefile for the Linux D-Bus domain socket layer.
  251. +#
  252. +
  253. +obj-$(CONFIG_DBUS)     += dbus.o
  254. +
  255. +dbus-y                 := af_dbus.o garbage.o matchrule.o message.o bus.o
  256. +dbus-$(CONFIG_SYSCTL)  += sysctl_net_dbus.o
  257. diff --git a/net/dbus/af_dbus.c b/net/dbus/af_dbus.c
  258. new file mode 100644
  259. index 0000000..3490223
  260. --- /dev/null
  261. +++ b/net/dbus/af_dbus.c
  262. @@ -0,0 +1,2103 @@
  263. +/*
  264. + * DBUS                Implementation of D-Bus domain sockets.
  265. + *
  266. + * Authors:    Alban Crequy <alban.crequy@collabora.co.uk>
  267. + *             Ian Molton <ian.molton@collabora.co.uk>
  268. + *
  269. + * Based on the BSD Unix domain sockets implementation.
  270. + *
  271. + * Authors:    Alan Cox, <alan@lxorguk.ukuu.org.uk>
  272. + *
  273. + *             This program is free software; you can redistribute it and/or
  274. + *             modify it under the terms of the GNU General Public License
  275. + *             as published by the Free Software Foundation; either version
  276. + *             2 of the License, or (at your option) any later version.
  277. + *
  278. + * Fixes:
  279. + *             Linus Torvalds  :       Assorted bug cures.
  280. + *             Niibe Yutaka    :       async I/O support.
  281. + *             Carsten Paeth   :       PF_UNIX check, address fixes.
  282. + *             Alan Cox        :       Limit size of allocated blocks.
  283. + *             Alan Cox        :       Fixed the stupid socketpair bug.
  284. + *             Alan Cox        :       BSD compatibility fine tuning.
  285. + *             Alan Cox        :       Fixed a bug in connect when interrupted.
  286. + *             Alan Cox        :       Sorted out a proper draft version of
  287. + *                                     file descriptor passing hacked up from
  288. + *                                     Mike Shaver's work.
  289. + *             Marty Leisner   :       Fixes to fd passing
  290. + *             Nick Nevin      :       recvmsg bugfix.
  291. + *             Alan Cox        :       Started proper garbage collector
  292. + *             Heiko EiBfeldt  :       Missing verify_area check
  293. + *             Alan Cox        :       Started POSIXisms
  294. + *             Andreas Schwab  :       Replace inode by dentry for proper
  295. + *                                     reference counting
  296. + *             Kirk Petersen   :       Made this a module
  297. + *         Christoph Rohland   :       Elegant non-blocking accept/connect algorithm.
  298. + *                                     Lots of bug fixes.
  299. + *          Alexey Kuznetosv   :       Repaired (I hope) bugs introduces
  300. + *                                     by above two patches.
  301. + *          Andrea Arcangeli   :       If possible we block in connect(2)
  302. + *                                     if the max backlog of the listen socket
  303. + *                                     is been reached. This won't break
  304. + *                                     old apps and it will avoid huge amount
  305. + *                                     of socks hashed (this for unix_gc()
  306. + *                                     performances reasons).
  307. + *                                     Security fix that limits the max
  308. + *                                     number of socks to 2*max_files and
  309. + *                                     the number of skb queueable in the
  310. + *                                     dgram receiver.
  311. + *             Artur Skawina   :       Hash function optimizations
  312. + *          Alexey Kuznetsov   :       Full scale SMP. Lot of bugs are introduced 8)
  313. + *           Malcolm Beattie   :       Set peercred for socketpair
  314. + *          Michal Ostrowski   :       Module initialization cleanup.
  315. + *          Arnaldo C. Melo    :       Remove MOD_{INC,DEC}_USE_COUNT,
  316. + *                                     the core infrastructure is doing that
  317. + *                                     for all net proto families now (2.5.69+)
  318. + *
  319. + *
  320. + * Known differences from reference BSD that was tested:
  321. + *
  322. + *     [TO FIX]
  323. + *     ECONNREFUSED is not returned from one end of a connected() socket to the
  324. + *             other the moment one end closes.
  325. + *     fstat() doesn't return st_dev=0, and give the blksize as high water mark
  326. + *             and a fake inode identifier (nor the BSD first socket fstat twice bug).
  327. + *     [NOT TO FIX]
  328. + *     accept() returns a path name even if the connecting socket has closed
  329. + *             in the meantime (BSD loses the path and gives up).
  330. + *     accept() returns 0 length path for an unbound connector. BSD returns 16
  331. + *             and a null first byte in the path (but not for gethost/peername - BSD bug ??)
  332. + *     socketpair(...SOCK_RAW..) doesn't panic the kernel.
  333. + *     BSD af_unix apparently has connect forgetting to block properly.
  334. + *             (need to check this with the POSIX spec in detail)
  335. + *
  336. + * Differences from 2.0.0-11-... (ANK)
  337. + *     Bug fixes and improvements.
  338. + *             - client shutdown killed server socket.
  339. + *             - removed all useless cli/sti pairs.
  340. + *
  341. + *     Semantic changes/extensions.
  342. + *             - generic control message passing.
  343. + *             - SCM_CREDENTIALS control message.
  344. + *             - "Abstract" (not FS based) socket bindings.
  345. + *               Abstract names are sequences of bytes (not zero terminated)
  346. + *               started by 0, so that this name space does not intersect
  347. + *               with BSD names.
  348. + */
  349. +
  350. +#include <linux/module.h>
  351. +#include <linux/kernel.h>
  352. +#include <linux/signal.h>
  353. +#include <linux/sched.h>
  354. +#include <linux/errno.h>
  355. +#include <linux/string.h>
  356. +#include <linux/stat.h>
  357. +#include <linux/dcache.h>
  358. +#include <linux/namei.h>
  359. +#include <linux/socket.h>
  360. +#include <linux/un.h>
  361. +#include <linux/fcntl.h>
  362. +#include <linux/termios.h>
  363. +#include <linux/sockios.h>
  364. +#include <linux/net.h>
  365. +#include <linux/in.h>
  366. +#include <linux/fs.h>
  367. +#include <linux/slab.h>
  368. +#include <asm/uaccess.h>
  369. +#include <linux/skbuff.h>
  370. +#include <linux/netdevice.h>
  371. +#include <net/net_namespace.h>
  372. +#include <net/sock.h>
  373. +#include <net/tcp_states.h>
  374. +#include <net/af_dbus.h>
  375. +#include <linux/proc_fs.h>
  376. +#include <linux/seq_file.h>
  377. +#include <net/scm.h>
  378. +#include <linux/init.h>
  379. +#include <linux/poll.h>
  380. +#include <linux/rtnetlink.h>
  381. +#include <linux/mount.h>
  382. +#include <net/checksum.h>
  383. +#include <linux/security.h>
  384. +
  385. +#include "dbus-protocol.h"
  386. +#include "matchrule.h"
  387. +#include "message.h"
  388. +#include "bus.h"
  389. +
  390. +static struct hlist_head dbus_socket_table[DBUS_HASH_SIZE + 1];
  391. +static DEFINE_SPINLOCK(dbus_table_lock);
  392. +static atomic_t dbus_nr_socks = ATOMIC_INIT(0);
  393. +
  394. +#define dbus_sockets_unbound   (&dbus_socket_table[DBUS_HASH_SIZE])
  395. +
  396. +#define DBUS_ABSTRACT(sk)      (dbus_sk(sk)->addr->hash != DBUS_HASH_SIZE)
  397. +
  398. +#ifdef CONFIG_SECURITY_NETWORK
  399. +static inline void dbus_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
  400. +{
  401. +       scm->secid = *DBUSSID(skb);
  402. +}
  403. +#else
  404. +static inline void dbus_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
  405. +{ }
  406. +#endif /* CONFIG_SECURITY_NETWORK */
  407. +
  408. +/*
  409. + *  SMP locking strategy:
  410. + *    hash table is protected with spinlock dbus_table_lock
  411. + *    each socket state is protected by separate rwlock.
  412. + */
  413. +
  414. +static inline unsigned dbus_hash_fold(__wsum n)
  415. +{
  416. +       unsigned hash = (__force unsigned)n;
  417. +       hash ^= hash>>16;
  418. +       hash ^= hash>>8;
  419. +       return hash&(DBUS_HASH_SIZE-1);
  420. +}
  421. +
  422. +#define dbus_peer(sk) (dbus_sk(sk)->peer)
  423. +
  424. +static inline int dbus_our_peer(struct sock *sk, struct sock *osk)
  425. +{
  426. +       return dbus_peer(osk) == sk;
  427. +}
  428. +
  429. +static inline int dbus_may_send(struct sock *sk, struct sock *osk)
  430. +{
  431. +       return dbus_peer(osk) == NULL || dbus_our_peer(sk, osk);
  432. +}
  433. +
  434. +static inline int dbus_recvq_full(struct sock const *sk)
  435. +{
  436. +       return skb_queue_len(&sk->sk_receive_queue) > sk->sk_max_ack_backlog;
  437. +}
  438. +
  439. +static struct sock *dbus_peer_get(struct sock *s)
  440. +{
  441. +       struct sock *peer;
  442. +
  443. +       dbus_state_lock(s);
  444. +       peer = dbus_peer(s);
  445. +       if (peer)
  446. +               sock_hold(peer);
  447. +       dbus_state_unlock(s);
  448. +       return peer;
  449. +}
  450. +
  451. +static inline void dbus_release_addr(struct dbus_address *addr)
  452. +{
  453. +       if (atomic_dec_and_test(&addr->refcnt))
  454. +               kfree(addr);
  455. +}
  456. +
  457. +/*
  458. + *     Check dbus socket name:
  459. + *             - should be not zero length.
  460. + *             - if started by not zero, should be NULL terminated (FS object)
  461. + *             - if started by zero, it is abstract name.
  462. + */
  463. +
  464. +static int dbus_mkname(struct sockaddr_un *sunaddr, int len, unsigned *hashp)
  465. +{
  466. +       if (len <= sizeof(short) || len > sizeof(*sunaddr))
  467. +               return -EINVAL;
  468. +       if (!sunaddr || sunaddr->sun_family != AF_DBUS)
  469. +               return -EINVAL;
  470. +       if (sunaddr->sun_path[0]) {
  471. +               /*
  472. +                * This may look like an off by one error but it is a bit more
  473. +                * subtle. 108 is the longest valid AF_DBUS path for a binding.
  474. +                * sun_path[108] doesnt as such exist.  However in kernel space
  475. +                * we are guaranteed that it is a valid memory location in our
  476. +                * kernel address buffer.
  477. +                */
  478. +               ((char *)sunaddr)[len] = 0;
  479. +               len = strlen(sunaddr->sun_path)+1+sizeof(short);
  480. +               return len;
  481. +       }
  482. +
  483. +       *hashp = dbus_hash_fold(csum_partial(sunaddr, len, 0));
  484. +       return len;
  485. +}
  486. +
  487. +static void __dbus_remove_socket(struct sock *sk)
  488. +{
  489. +       sk_del_node_init(sk);
  490. +}
  491. +
  492. +static void __dbus_insert_socket(struct hlist_head *list, struct sock *sk)
  493. +{
  494. +       WARN_ON(!sk_unhashed(sk));
  495. +       sk_add_node(sk, list);
  496. +}
  497. +
  498. +static inline void dbus_remove_socket(struct sock *sk)
  499. +{
  500. +       spin_lock(&dbus_table_lock);
  501. +       __dbus_remove_socket(sk);
  502. +       spin_unlock(&dbus_table_lock);
  503. +}
  504. +
  505. +static inline void dbus_insert_socket(struct hlist_head *list, struct sock *sk)
  506. +{
  507. +       spin_lock(&dbus_table_lock);
  508. +       __dbus_insert_socket(list, sk);
  509. +       spin_unlock(&dbus_table_lock);
  510. +}
  511. +
  512. +static struct sock *__dbus_find_socket_byname(struct net *net,
  513. +                                             struct sockaddr_un *sunname,
  514. +                                             int len, int type, unsigned hash)
  515. +{
  516. +       struct sock *s;
  517. +       struct hlist_node *node;
  518. +
  519. +       sk_for_each(s, node, &dbus_socket_table[hash ^ type]) {
  520. +               struct dbus_sock *u = dbus_sk(s);
  521. +
  522. +               if (!net_eq(sock_net(s), net))
  523. +                       continue;
  524. +
  525. +               if (u->addr->len == len &&
  526. +                   !memcmp(u->addr->name, sunname, len))
  527. +                       goto found;
  528. +       }
  529. +       s = NULL;
  530. +found:
  531. +       return s;
  532. +}
  533. +
  534. +static inline struct sock *dbus_find_socket_byname(struct net *net,
  535. +                                                  struct sockaddr_un *sunname,
  536. +                                                  int len, int type,
  537. +                                                  unsigned hash)
  538. +{
  539. +       struct sock *s;
  540. +
  541. +       spin_lock(&dbus_table_lock);
  542. +       s = __dbus_find_socket_byname(net, sunname, len, type, hash);
  543. +       if (s)
  544. +               sock_hold(s);
  545. +       spin_unlock(&dbus_table_lock);
  546. +       return s;
  547. +}
  548. +
  549. +static struct sock *dbus_find_socket_byinode(struct net *net, struct inode *i)
  550. +{
  551. +       struct sock *s;
  552. +       struct hlist_node *node;
  553. +
  554. +       spin_lock(&dbus_table_lock);
  555. +       sk_for_each(s, node,
  556. +                   &dbus_socket_table[i->i_ino & (DBUS_HASH_SIZE - 1)]) {
  557. +               struct dentry *dentry = dbus_sk(s)->dentry;
  558. +
  559. +               if (!net_eq(sock_net(s), net))
  560. +                       continue;
  561. +
  562. +               if (dentry && dentry->d_inode == i) {
  563. +                       sock_hold(s);
  564. +                       goto found;
  565. +               }
  566. +       }
  567. +       s = NULL;
  568. +found:
  569. +       spin_unlock(&dbus_table_lock);
  570. +       return s;
  571. +}
  572. +
  573. +static inline int dbus_writable(struct sock *sk)
  574. +{
  575. +       return (atomic_read(&sk->sk_wmem_alloc) << 2) <= sk->sk_sndbuf;
  576. +}
  577. +
  578. +static void dbus_write_space(struct sock *sk)
  579. +{
  580. +       struct socket_wq *wq;
  581. +
  582. +       rcu_read_lock();
  583. +       if (dbus_writable(sk)) {
  584. +               wq = rcu_dereference(sk->sk_wq);
  585. +               if (wq_has_sleeper(wq))
  586. +                       wake_up_interruptible_sync(&wq->wait);
  587. +               sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
  588. +       }
  589. +       rcu_read_unlock();
  590. +}
  591. +
  592. +static void dbus_sock_destructor(struct sock *sk)
  593. +{
  594. +       struct dbus_sock *u = dbus_sk(sk);
  595. +
  596. +       skb_queue_purge(&sk->sk_receive_queue);
  597. +
  598. +       WARN_ON(atomic_read(&sk->sk_wmem_alloc));
  599. +       WARN_ON(!sk_unhashed(sk));
  600. +       WARN_ON(sk->sk_socket);
  601. +       if (!sock_flag(sk, SOCK_DEAD)) {
  602. +               printk(KERN_INFO "Attempt to release alive dbus socket: %p\n", sk);
  603. +               return;
  604. +       }
  605. +
  606. +       if (!u->daemon_side &&u->uniq_name &&
  607. +            u->authenticated) {
  608. +               bus_matchmaker_disconnected(u->bus->matchmaker, u);
  609. +               dbus_bus_disconnected(u->bus, u);
  610. +       }
  611. +
  612. +       if (u->addr)
  613. +               dbus_release_addr(u->addr);
  614. +
  615. +       if (u->priv) {
  616. +               kfree(u->priv);
  617. +               u->priv = NULL;
  618. +       }
  619. +
  620. +       if (u->bus) {
  621. +               u->bus = NULL;
  622. +       }
  623. +
  624. +       atomic_dec(&dbus_nr_socks);
  625. +       local_bh_disable();
  626. +       sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
  627. +       local_bh_enable();
  628. +#ifdef DBUS_REFCNT_DEBUG
  629. +       printk(KERN_DEBUG "DBUS %p is destroyed, %d are still alive.\n", sk,
  630. +               atomic_read(&dbus_nr_socks));
  631. +#endif
  632. +}
  633. +
  634. +static int dbus_release_sock(struct sock *sk, int embrion)
  635. +{
  636. +       struct dbus_sock *u = dbus_sk(sk);
  637. +       struct dentry *dentry;
  638. +       struct vfsmount *mnt;
  639. +       struct sock *skpair;
  640. +       struct sk_buff *skb;
  641. +       int state;
  642. +
  643. +       dbus_remove_socket(sk);
  644. +
  645. +       /* Clear state */
  646. +       dbus_state_lock(sk);
  647. +       sock_orphan(sk);
  648. +       sk->sk_shutdown = SHUTDOWN_MASK;
  649. +       dentry       = u->dentry;
  650. +       u->dentry    = NULL;
  651. +       mnt          = u->mnt;
  652. +       u->mnt       = NULL;
  653. +       state = sk->sk_state;
  654. +       sk->sk_state = TCP_CLOSE;
  655. +       dbus_state_unlock(sk);
  656. +
  657. +       wake_up_interruptible_all(&u->peer_wait);
  658. +
  659. +       skpair = dbus_peer(sk);
  660. +
  661. +       if (skpair != NULL) {
  662. +               if (sk->sk_type == SOCK_STREAM) {
  663. +                       dbus_state_lock(skpair);
  664. +                       /* No more writes */
  665. +                       skpair->sk_shutdown = SHUTDOWN_MASK;
  666. +                       if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)
  667. +                               skpair->sk_err = ECONNRESET;
  668. +                       dbus_state_unlock(skpair);
  669. +                       skpair->sk_state_change(skpair);
  670. +                       sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP);
  671. +               }
  672. +               sock_put(skpair); /* It may now die */
  673. +               dbus_peer(sk) = NULL;
  674. +       }
  675. +
  676. +       /* Try to flush out this socket. Throw out buffers at least */
  677. +
  678. +       while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
  679. +               if (state == TCP_LISTEN)
  680. +                       dbus_release_sock(skb->sk, 1);
  681. +               /* passed fds are erased in the kfree_skb hook        */
  682. +               kfree_skb(skb);
  683. +       }
  684. +
  685. +       if (dentry) {
  686. +               dput(dentry);
  687. +               mntput(mnt);
  688. +       }
  689. +
  690. +       sock_put(sk);
  691. +
  692. +       /* ---- Socket is dead now and most probably destroyed ---- */
  693. +
  694. +       /*
  695. +        * Fixme: BSD difference: In BSD all sockets connected to use get
  696. +        *        ECONNRESET and we die on the spot. In Linux we behave
  697. +        *        like files and pipes do and wait for the last
  698. +        *        dereference.
  699. +        *
  700. +        * Can't we simply set sock->err?
  701. +        *
  702. +        *        What the above comment does talk about? --ANK(980817)
  703. +        */
  704. +
  705. +       if (dbus_tot_inflight)
  706. +               dbus_gc();              /* Garbage collect fds */
  707. +
  708. +       return 0;
  709. +}
  710. +
  711. +static int dbus_listen(struct socket *sock, int backlog)
  712. +{
  713. +       int err;
  714. +       struct sock *sk = sock->sk;
  715. +       struct dbus_sock *u = dbus_sk(sk);
  716. +
  717. +       err = -EOPNOTSUPP;
  718. +       if (sock->type != SOCK_STREAM)
  719. +               goto out;       /* Only stream sockets accept */
  720. +       err = -EINVAL;
  721. +       if (!u->addr)
  722. +               goto out;       /* No listens on an unbound socket */
  723. +
  724. +        u->bus->matchmaker = bus_matchmaker_new();
  725. +
  726. +       dbus_state_lock(sk);
  727. +       if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN)
  728. +               goto out_unlock;
  729. +       if (backlog > sk->sk_max_ack_backlog)
  730. +               wake_up_interruptible_all(&u->peer_wait);
  731. +       sk->sk_max_ack_backlog  = backlog;
  732. +       sk->sk_state            = TCP_LISTEN;
  733. +       /* set credentials so connect can copy them */
  734. +       sk->sk_peercred.pid     = task_tgid_vnr(current);
  735. +       current_euid_egid(&sk->sk_peercred.uid, &sk->sk_peercred.gid);
  736. +       err = 0;
  737. +
  738. +out_unlock:
  739. +       dbus_state_unlock(sk);
  740. +out:
  741. +       return err;
  742. +}
  743. +
  744. +static int dbus_release(struct socket *);
  745. +static int dbus_bind(struct socket *, struct sockaddr *, int);
  746. +static int dbus_stream_connect(struct socket *, struct sockaddr *,
  747. +                              int addr_len, int flags);
  748. +static int dbus_socketpair(struct socket *, struct socket *);
  749. +static int dbus_accept(struct socket *, struct socket *, int);
  750. +static int dbus_getname(struct socket *, struct sockaddr *, int *, int);
  751. +static unsigned int dbus_poll(struct file *, struct socket *, poll_table *);
  752. +static int dbus_ioctl(struct socket *, unsigned int, unsigned long);
  753. +static int dbus_shutdown(struct socket *, int);
  754. +static int dbus_stream_sendmsg(struct kiocb *, struct socket *,
  755. +                              struct msghdr *, size_t);
  756. +static int dbus_stream_recvmsg(struct kiocb *, struct socket *,
  757. +                              struct msghdr *, size_t, int);
  758. +
  759. +static const struct proto_ops dbus_stream_ops = {
  760. +       .family =       PF_DBUS,
  761. +       .owner =        THIS_MODULE,
  762. +       .release =      dbus_release,
  763. +       .bind =         dbus_bind,
  764. +       .connect =      dbus_stream_connect,
  765. +       .socketpair =   dbus_socketpair,
  766. +       .accept =       dbus_accept,
  767. +       .getname =      dbus_getname,
  768. +       .poll =         dbus_poll,
  769. +       .ioctl =        dbus_ioctl,
  770. +       .listen =       dbus_listen,
  771. +       .shutdown =     dbus_shutdown,
  772. +       .setsockopt =   sock_no_setsockopt,
  773. +       .getsockopt =   sock_no_getsockopt,
  774. +       .sendmsg =      dbus_stream_sendmsg,
  775. +       .recvmsg =      dbus_stream_recvmsg,
  776. +       .mmap =         sock_no_mmap,
  777. +       .sendpage =     sock_no_sendpage,
  778. +};
  779. +
  780. +static struct proto dbus_proto = {
  781. +       .name                   = "DBUS",
  782. +       .owner                  = THIS_MODULE,
  783. +       .obj_size               = sizeof(struct dbus_sock),
  784. +};
  785. +
  786. +struct dbus_sock_priv {
  787. +       int disabled;
  788. +};
  789. +
  790. +/*
  791. + * AF_DBUS sockets do not interact with hardware, hence they
  792. + * dont trigger interrupts - so it's safe for them to have
  793. + * bh-unsafe locking for their sk_receive_queue.lock. Split off
  794. + * this special lock-class by reinitializing the spinlock key:
  795. + */
  796. +static struct lock_class_key af_dbus_sk_receive_queue_lock_key;
  797. +
  798. +static struct sock *dbus_create1(struct net *net, struct socket *sock)
  799. +{
  800. +       struct sock *sk = NULL;
  801. +       struct dbus_sock *u;
  802. +       struct dbus_sock_priv *priv = NULL;
  803. +
  804. +       atomic_inc(&dbus_nr_socks);
  805. +       if (atomic_read(&dbus_nr_socks) > 2 * get_max_files())
  806. +               goto out;
  807. +
  808. +       priv = kzalloc(sizeof(struct dbus_sock_priv), GFP_KERNEL);
  809. +       if (!priv)
  810. +               goto out;
  811. +
  812. +       sk = sk_alloc(net, PF_DBUS, GFP_KERNEL, &dbus_proto);
  813. +       if (!sk) {
  814. +               kfree(priv);
  815. +               goto out;
  816. +       }
  817. +
  818. +       sock_init_data(sock, sk);
  819. +       lockdep_set_class(&sk->sk_receive_queue.lock,
  820. +                               &af_dbus_sk_receive_queue_lock_key);
  821. +
  822. +       sk->sk_write_space      = dbus_write_space;
  823. +       sk->sk_max_ack_backlog  = net->unx.sysctl_max_dgram_qlen;
  824. +       sk->sk_destruct         = dbus_sock_destructor;
  825. +       u         = dbus_sk(sk);
  826. +       u->dentry = NULL;
  827. +       u->mnt    = NULL;
  828. +       spin_lock_init(&u->lock);
  829. +       atomic_long_set(&u->inflight, 0);
  830. +       INIT_LIST_HEAD(&u->link);
  831. +       mutex_init(&u->readlock); /* single task reading lock */
  832. +       init_waitqueue_head(&u->peer_wait);
  833. +       u->priv = priv;
  834. +       u->daemon_side = 0;
  835. +       u->authenticated = 0;
  836. +       u->uniq_name = NULL;
  837. +       u->bus = NULL;
  838. +       INIT_HLIST_NODE(&u->bus_link);
  839. +       dbus_insert_socket(dbus_sockets_unbound, sk);
  840. +out:
  841. +       if (sk == NULL)
  842. +               atomic_dec(&dbus_nr_socks);
  843. +       else {
  844. +               local_bh_disable();
  845. +               sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
  846. +               local_bh_enable();
  847. +       }
  848. +       return sk;
  849. +}
  850. +
  851. +static int dbus_create(struct net *net, struct socket *sock, int protocol,
  852. +                      int kern)
  853. +{
  854. +       if (protocol && protocol != PF_DBUS)
  855. +               return -EPROTONOSUPPORT;
  856. +
  857. +       sock->state = SS_UNCONNECTED;
  858. +
  859. +       switch (sock->type) {
  860. +       case SOCK_STREAM:
  861. +               sock->ops = &dbus_stream_ops;
  862. +               break;
  863. +               /*
  864. +                *      Believe it or not BSD has AF_UNIX, SOCK_RAW though
  865. +                *      nothing uses it.
  866. +                */
  867. +       default:
  868. +               return -ESOCKTNOSUPPORT;
  869. +       }
  870. +
  871. +       return dbus_create1(net, sock) ? 0 : -ENOMEM;
  872. +}
  873. +
  874. +static int dbus_release(struct socket *sock)
  875. +{
  876. +       struct sock *sk = sock->sk;
  877. +
  878. +       if (!sk)
  879. +               return 0;
  880. +
  881. +       sock->sk = NULL;
  882. +
  883. +       return dbus_release_sock(sk, 0);
  884. +}
  885. +
  886. +static int dbus_autobind(struct socket *sock)
  887. +{
  888. +       struct sock *sk = sock->sk;
  889. +       struct net *net = sock_net(sk);
  890. +       struct dbus_sock *u = dbus_sk(sk);
  891. +       static u32 ordernum = 1;
  892. +       struct dbus_address *addr;
  893. +       int err;
  894. +
  895. +       mutex_lock(&u->readlock);
  896. +
  897. +       err = 0;
  898. +       if (u->addr)
  899. +               goto out;
  900. +
  901. +       err = -ENOMEM;
  902. +       addr = kzalloc(sizeof(*addr) + sizeof(short) + 16, GFP_KERNEL);
  903. +       if (!addr)
  904. +               goto out;
  905. +
  906. +       addr->name->sun_family = AF_DBUS;
  907. +       atomic_set(&addr->refcnt, 1);
  908. +
  909. +retry:
  910. +       addr->len = sprintf(addr->name->sun_path+1, "%05x", ordernum) + 1 + sizeof(short);
  911. +       addr->hash = dbus_hash_fold(csum_partial(addr->name, addr->len, 0));
  912. +
  913. +       spin_lock(&dbus_table_lock);
  914. +       ordernum = (ordernum+1)&0xFFFFF;
  915. +
  916. +       if (__dbus_find_socket_byname(net, addr->name, addr->len, sock->type,
  917. +                                     addr->hash)) {
  918. +               spin_unlock(&dbus_table_lock);
  919. +               /* Sanity yield. It is unusual case, but yet... */
  920. +               if (!(ordernum&0xFF))
  921. +                       yield();
  922. +               goto retry;
  923. +       }
  924. +       addr->hash ^= sk->sk_type;
  925. +
  926. +       __dbus_remove_socket(sk);
  927. +       u->addr = addr;
  928. +       __dbus_insert_socket(&dbus_socket_table[addr->hash], sk);
  929. +       spin_unlock(&dbus_table_lock);
  930. +       err = 0;
  931. +
  932. +out:   mutex_unlock(&u->readlock);
  933. +       return err;
  934. +}
  935. +
  936. +static struct sock *dbus_find_other(struct net *net,
  937. +                                   struct sockaddr_un *sunname, int len,
  938. +                                   int type, unsigned hash, int *error)
  939. +{
  940. +       struct sock *u;
  941. +       struct path path;
  942. +       int err = 0;
  943. +
  944. +       if (sunname->sun_path[0]) {
  945. +               struct inode *inode;
  946. +               err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path);
  947. +               if (err)
  948. +                       goto fail;
  949. +               inode = path.dentry->d_inode;
  950. +               err = inode_permission(inode, MAY_WRITE);
  951. +               if (err)
  952. +                       goto put_fail;
  953. +
  954. +               err = -ECONNREFUSED;
  955. +               if (!S_ISSOCK(inode->i_mode))
  956. +                       goto put_fail;
  957. +               u = dbus_find_socket_byinode(net, inode);
  958. +               if (!u)
  959. +                       goto put_fail;
  960. +
  961. +               if (u->sk_type == type)
  962. +                       touch_atime(path.mnt, path.dentry);
  963. +
  964. +               path_put(&path);
  965. +
  966. +               err = -EPROTOTYPE;
  967. +               if (u->sk_type != type) {
  968. +                       sock_put(u);
  969. +                       goto fail;
  970. +               }
  971. +       } else {
  972. +               err = -ECONNREFUSED;
  973. +               u = dbus_find_socket_byname(net, sunname, len, type, hash);
  974. +               if (u) {
  975. +                       struct dentry *dentry;
  976. +                       dentry = dbus_sk(u)->dentry;
  977. +                       if (dentry)
  978. +                               touch_atime(dbus_sk(u)->mnt, dentry);
  979. +               } else
  980. +                       goto fail;
  981. +       }
  982. +       return u;
  983. +
  984. +put_fail:
  985. +       path_put(&path);
  986. +fail:
  987. +       *error = err;
  988. +       return NULL;
  989. +}
  990. +
  991. +
  992. +static int dbus_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
  993. +{
  994. +       struct sock *sk = sock->sk;
  995. +       struct net *net = sock_net(sk);
  996. +       struct dbus_sock *u = dbus_sk(sk);
  997. +       struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
  998. +       struct dentry *dentry = NULL;
  999. +       struct nameidata nd;
  1000. +       int err;
  1001. +       unsigned hash;
  1002. +       struct dbus_address *addr;
  1003. +       struct hlist_head *list;
  1004. +
  1005. +       err = -EINVAL;
  1006. +       if (sunaddr->sun_family != AF_DBUS)
  1007. +               goto out;
  1008. +
  1009. +       if (addr_len == sizeof(short)) {
  1010. +               err = dbus_autobind(sock);
  1011. +               goto out;
  1012. +       }
  1013. +
  1014. +       err = dbus_mkname(sunaddr, addr_len, &hash);
  1015. +       if (err < 0)
  1016. +               goto out;
  1017. +       addr_len = err;
  1018. +
  1019. +       mutex_lock(&u->readlock);
  1020. +
  1021. +       err = -EINVAL;
  1022. +       if (u->addr)
  1023. +               goto out_up;
  1024. +
  1025. +       err = -ENOMEM;
  1026. +       addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL);
  1027. +       if (!addr)
  1028. +               goto out_up;
  1029. +
  1030. +       u->bus = dbus_bus_new();
  1031. +       if (!u->bus) {
  1032. +               kfree(addr);
  1033. +               goto out;
  1034. +       }
  1035. +
  1036. +       memcpy(addr->name, sunaddr, addr_len);
  1037. +       addr->len = addr_len;
  1038. +       addr->hash = hash ^ sk->sk_type;
  1039. +       atomic_set(&addr->refcnt, 1);
  1040. +
  1041. +       if (sunaddr->sun_path[0]) {
  1042. +               unsigned int mode;
  1043. +               err = 0;
  1044. +               /*
  1045. +                * Get the parent directory, calculate the hash for last
  1046. +                * component.
  1047. +                */
  1048. +               err = path_lookup(sunaddr->sun_path, LOOKUP_PARENT, &nd);
  1049. +               if (err)
  1050. +                       goto out_mknod_parent;
  1051. +
  1052. +               dentry = lookup_create(&nd, 0);
  1053. +               err = PTR_ERR(dentry);
  1054. +               if (IS_ERR(dentry))
  1055. +                       goto out_mknod_unlock;
  1056. +
  1057. +               /*
  1058. +                * All right, let's create it.
  1059. +                */
  1060. +               mode = S_IFSOCK |
  1061. +                      (SOCK_INODE(sock)->i_mode & ~current_umask());
  1062. +               err = mnt_want_write(nd.path.mnt);
  1063. +               if (err)
  1064. +                       goto out_mknod_dput;
  1065. +               err = security_path_mknod(&nd.path, dentry, mode, 0);
  1066. +               if (err)
  1067. +                       goto out_mknod_drop_write;
  1068. +               err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
  1069. +out_mknod_drop_write:
  1070. +               mnt_drop_write(nd.path.mnt);
  1071. +               if (err)
  1072. +                       goto out_mknod_dput;
  1073. +               mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
  1074. +               dput(nd.path.dentry);
  1075. +               nd.path.dentry = dentry;
  1076. +
  1077. +               addr->hash = DBUS_HASH_SIZE;
  1078. +       }
  1079. +
  1080. +       spin_lock(&dbus_table_lock);
  1081. +
  1082. +       if (!sunaddr->sun_path[0]) {
  1083. +               err = -EADDRINUSE;
  1084. +               if (__dbus_find_socket_byname(net, sunaddr, addr_len,
  1085. +                                             sk->sk_type, hash)) {
  1086. +                       dbus_release_addr(addr);
  1087. +                       goto out_unlock;
  1088. +               }
  1089. +
  1090. +               list = &dbus_socket_table[addr->hash];
  1091. +       } else {
  1092. +               list = &dbus_socket_table[dentry->d_inode->i_ino & (DBUS_HASH_SIZE-1)];
  1093. +               u->dentry = nd.path.dentry;
  1094. +               u->mnt    = nd.path.mnt;
  1095. +       }
  1096. +
  1097. +       err = 0;
  1098. +       __dbus_remove_socket(sk);
  1099. +       u->addr = addr;
  1100. +       __dbus_insert_socket(list, sk);
  1101. +
  1102. +out_unlock:
  1103. +       spin_unlock(&dbus_table_lock);
  1104. +out_up:
  1105. +       mutex_unlock(&u->readlock);
  1106. +out:
  1107. +       return err;
  1108. +
  1109. +out_mknod_dput:
  1110. +       dput(dentry);
  1111. +out_mknod_unlock:
  1112. +       mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
  1113. +       path_put(&nd.path);
  1114. +out_mknod_parent:
  1115. +       if (err == -EEXIST)
  1116. +               err = -EADDRINUSE;
  1117. +       dbus_release_addr(addr);
  1118. +       goto out_up;
  1119. +}
  1120. +
  1121. +static long dbus_wait_for_peer(struct sock *other, long timeo)
  1122. +{
  1123. +       struct dbus_sock *u = dbus_sk(other);
  1124. +       int sched;
  1125. +       DEFINE_WAIT(wait);
  1126. +
  1127. +       prepare_to_wait_exclusive(&u->peer_wait, &wait, TASK_INTERRUPTIBLE);
  1128. +
  1129. +       sched = !sock_flag(other, SOCK_DEAD) &&
  1130. +               !(other->sk_shutdown & RCV_SHUTDOWN) &&
  1131. +               dbus_recvq_full(other);
  1132. +
  1133. +       dbus_state_unlock(other);
  1134. +
  1135. +       if (sched)
  1136. +               timeo = schedule_timeout(timeo);
  1137. +
  1138. +       finish_wait(&u->peer_wait, &wait);
  1139. +       return timeo;
  1140. +}
  1141. +
  1142. +static int dbus_stream_connect(struct socket *sock, struct sockaddr *uaddr,
  1143. +                              int addr_len, int flags)
  1144. +{
  1145. +       struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
  1146. +       struct sock *sk = sock->sk;
  1147. +       struct net *net = sock_net(sk);
  1148. +       struct dbus_sock *u = dbus_sk(sk), *newu, *otheru;
  1149. +       struct sock *newsk = NULL;
  1150. +       struct sock *other = NULL;
  1151. +       struct sk_buff *skb = NULL;
  1152. +       unsigned hash;
  1153. +       int st;
  1154. +       int err;
  1155. +       long timeo;
  1156. +
  1157. +       err = dbus_mkname(sunaddr, addr_len, &hash);
  1158. +       if (err < 0)
  1159. +               goto out;
  1160. +       addr_len = err;
  1161. +
  1162. +       if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr &&
  1163. +           (err = dbus_autobind(sock)) != 0)
  1164. +               goto out;
  1165. +
  1166. +       timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
  1167. +
  1168. +       /* First of all allocate resources.
  1169. +          If we will make it after state is locked,
  1170. +          we will have to recheck all again in any case.
  1171. +        */
  1172. +
  1173. +       err = -ENOMEM;
  1174. +
  1175. +       /* create new sock for complete connection */
  1176. +       newsk = dbus_create1(sock_net(sk), NULL);
  1177. +       if (newsk == NULL)
  1178. +               goto out;
  1179. +
  1180. +       /* Allocate skb for sending to listening sock */
  1181. +       skb = sock_wmalloc(newsk, 1, 0, GFP_KERNEL);
  1182. +       if (skb == NULL)
  1183. +               goto out;
  1184. +
  1185. +restart:
  1186. +       /*  Find listening sock. */
  1187. +       other = dbus_find_other(net, sunaddr, addr_len, sk->sk_type, hash, &err);
  1188. +       if (!other)
  1189. +               goto out;
  1190. +
  1191. +       /* Latch state of peer */
  1192. +       dbus_state_lock(other);
  1193. +
  1194. +       /* Apparently VFS overslept socket death. Retry. */
  1195. +       if (sock_flag(other, SOCK_DEAD)) {
  1196. +               dbus_state_unlock(other);
  1197. +               sock_put(other);
  1198. +               goto restart;
  1199. +       }
  1200. +
  1201. +       err = -ECONNREFUSED;
  1202. +       if (other->sk_state != TCP_LISTEN)
  1203. +               goto out_unlock;
  1204. +       if (other->sk_shutdown & RCV_SHUTDOWN)
  1205. +               goto out_unlock;
  1206. +
  1207. +       if (dbus_recvq_full(other)) {
  1208. +               err = -EAGAIN;
  1209. +               if (!timeo)
  1210. +                       goto out_unlock;
  1211. +
  1212. +               timeo = dbus_wait_for_peer(other, timeo);
  1213. +
  1214. +               err = sock_intr_errno(timeo);
  1215. +               if (signal_pending(current))
  1216. +                       goto out;
  1217. +               sock_put(other);
  1218. +               goto restart;
  1219. +       }
  1220. +
  1221. +       /* Latch our state.
  1222. +
  1223. +          It is tricky place. We need to grab write lock and cannot
  1224. +          drop lock on peer. It is dangerous because deadlock is
  1225. +          possible. Connect to self case and simultaneous
  1226. +          attempt to connect are eliminated by checking socket
  1227. +          state. other is TCP_LISTEN, if sk is TCP_LISTEN we
  1228. +          check this before attempt to grab lock.
  1229. +
  1230. +          Well, and we have to recheck the state after socket locked.
  1231. +        */
  1232. +       st = sk->sk_state;
  1233. +
  1234. +       switch (st) {
  1235. +       case TCP_CLOSE:
  1236. +               /* This is ok... continue with connect */
  1237. +               break;
  1238. +       case TCP_ESTABLISHED:
  1239. +               /* Socket is already connected */
  1240. +               err = -EISCONN;
  1241. +               goto out_unlock;
  1242. +       default:
  1243. +               err = -EINVAL;
  1244. +               goto out_unlock;
  1245. +       }
  1246. +
  1247. +       dbus_state_lock_nested(sk);
  1248. +
  1249. +       if (sk->sk_state != st) {
  1250. +               dbus_state_unlock(sk);
  1251. +               dbus_state_unlock(other);
  1252. +               sock_put(other);
  1253. +               goto restart;
  1254. +       }
  1255. +
  1256. +       err = security_dbus_stream_connect(sock, other->sk_socket, newsk);
  1257. +       if (err) {
  1258. +               dbus_state_unlock(sk);
  1259. +               goto out_unlock;
  1260. +       }
  1261. +
  1262. +       /* The way is open! Fastly set all the necessary fields... */
  1263. +
  1264. +       sock_hold(sk);
  1265. +       dbus_peer(newsk)        = sk;
  1266. +       newsk->sk_state         = TCP_ESTABLISHED;
  1267. +       newsk->sk_type          = sk->sk_type;
  1268. +       newsk->sk_peercred.pid  = task_tgid_vnr(current);
  1269. +       current_euid_egid(&newsk->sk_peercred.uid, &newsk->sk_peercred.gid);
  1270. +       newu = dbus_sk(newsk);
  1271. +       newu->daemon_side       = 1;
  1272. +       newsk->sk_wq            = &newu->peer_wq;
  1273. +       otheru = dbus_sk(other);
  1274. +       newu->bus = otheru->bus;
  1275. +       u->bus = otheru->bus;
  1276. +
  1277. +       /* copy address information from listening to new sock*/
  1278. +       if (otheru->addr) {
  1279. +               atomic_inc(&otheru->addr->refcnt);
  1280. +               newu->addr = otheru->addr;
  1281. +       }
  1282. +       if (otheru->dentry) {
  1283. +               newu->dentry    = dget(otheru->dentry);
  1284. +               newu->mnt       = mntget(otheru->mnt);
  1285. +       }
  1286. +
  1287. +       /* Set credentials */
  1288. +       sk->sk_peercred = other->sk_peercred;
  1289. +
  1290. +       sock->state     = SS_CONNECTED;
  1291. +       sk->sk_state    = TCP_ESTABLISHED;
  1292. +       sock_hold(newsk);
  1293. +
  1294. +       smp_mb__after_atomic_inc();     /* sock_hold() does an atomic_inc() */
  1295. +       dbus_peer(sk)   = newsk;
  1296. +
  1297. +       dbus_state_unlock(sk);
  1298. +
  1299. +       /* take ten and and send info to listening sock */
  1300. +       spin_lock(&other->sk_receive_queue.lock);
  1301. +       __skb_queue_tail(&other->sk_receive_queue, skb);
  1302. +       spin_unlock(&other->sk_receive_queue.lock);
  1303. +       dbus_state_unlock(other);
  1304. +       other->sk_data_ready(other, 0);
  1305. +       sock_put(other);
  1306. +       return 0;
  1307. +
  1308. +out_unlock:
  1309. +       if (other)
  1310. +               dbus_state_unlock(other);
  1311. +
  1312. +out:
  1313. +       kfree_skb(skb);
  1314. +       if (newsk)
  1315. +               dbus_release_sock(newsk, 0);
  1316. +       if (other)
  1317. +               sock_put(other);
  1318. +       return err;
  1319. +}
  1320. +
  1321. +static int dbus_socketpair(struct socket *socka, struct socket *sockb)
  1322. +{
  1323. +       struct sock *ska = socka->sk, *skb = sockb->sk;
  1324. +
  1325. +       /* Join our sockets back to back */
  1326. +       sock_hold(ska);
  1327. +       sock_hold(skb);
  1328. +       dbus_peer(ska) = skb;
  1329. +       dbus_peer(skb) = ska;
  1330. +       ska->sk_peercred.pid = skb->sk_peercred.pid = task_tgid_vnr(current);
  1331. +       current_euid_egid(&skb->sk_peercred.uid, &skb->sk_peercred.gid);
  1332. +       ska->sk_peercred.uid = skb->sk_peercred.uid;
  1333. +       ska->sk_peercred.gid = skb->sk_peercred.gid;
  1334. +
  1335. +       if (ska->sk_type != SOCK_DGRAM) {
  1336. +               ska->sk_state = TCP_ESTABLISHED;
  1337. +               skb->sk_state = TCP_ESTABLISHED;
  1338. +               socka->state  = SS_CONNECTED;
  1339. +               sockb->state  = SS_CONNECTED;
  1340. +       }
  1341. +       return 0;
  1342. +}
  1343. +
  1344. +static int dbus_accept(struct socket *sock, struct socket *newsock, int flags)
  1345. +{
  1346. +       struct sock *sk = sock->sk;
  1347. +       struct sock *tsk;
  1348. +       struct sk_buff *skb;
  1349. +       int err;
  1350. +
  1351. +       err = -EOPNOTSUPP;
  1352. +       if (sock->type != SOCK_STREAM && sock->type)
  1353. +               goto out;
  1354. +
  1355. +       err = -EINVAL;
  1356. +       if (sk->sk_state != TCP_LISTEN)
  1357. +               goto out;
  1358. +
  1359. +       /* If socket state is TCP_LISTEN it cannot change (for now...),
  1360. +        * so that no locks are necessary.
  1361. +        */
  1362. +
  1363. +       skb = skb_recv_datagram(sk, 0, flags&O_NONBLOCK, &err);
  1364. +       if (!skb) {
  1365. +               /* This means receive shutdown. */
  1366. +               if (err == 0)
  1367. +                       err = -EINVAL;
  1368. +               goto out;
  1369. +       }
  1370. +
  1371. +       tsk = skb->sk;
  1372. +       skb_free_datagram(sk, skb);
  1373. +       wake_up_interruptible(&dbus_sk(sk)->peer_wait);
  1374. +
  1375. +       /* attach accepted sock to socket */
  1376. +       dbus_state_lock(tsk);
  1377. +       newsock->state = SS_CONNECTED;
  1378. +       sock_graft(tsk, newsock);
  1379. +       dbus_state_unlock(tsk);
  1380. +       return 0;
  1381. +
  1382. +out:
  1383. +       return err;
  1384. +}
  1385. +
  1386. +
  1387. +static int dbus_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
  1388. +{
  1389. +       struct sock *sk = sock->sk;
  1390. +       struct dbus_sock *u;
  1391. +       DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, uaddr);
  1392. +       int err = 0;
  1393. +
  1394. +       if (peer) {
  1395. +               sk = dbus_peer_get(sk);
  1396. +
  1397. +               err = -ENOTCONN;
  1398. +               if (!sk)
  1399. +                       goto out;
  1400. +               err = 0;
  1401. +       } else {
  1402. +               sock_hold(sk);
  1403. +       }
  1404. +
  1405. +       u = dbus_sk(sk);
  1406. +       dbus_state_lock(sk);
  1407. +       if (!u->addr) {
  1408. +               sunaddr->sun_family = AF_DBUS;
  1409. +               sunaddr->sun_path[0] = 0;
  1410. +               *uaddr_len = sizeof(short);
  1411. +       } else {
  1412. +               struct dbus_address *addr = u->addr;
  1413. +
  1414. +               *uaddr_len = addr->len;
  1415. +               memcpy(sunaddr, addr->name, *uaddr_len);
  1416. +       }
  1417. +       dbus_state_unlock(sk);
  1418. +       sock_put(sk);
  1419. +out:
  1420. +       return err;
  1421. +}
  1422. +
  1423. +static void dbus_detach_fds(struct scm_cookie *scm, struct sk_buff *skb)
  1424. +{
  1425. +       int i;
  1426. +
  1427. +       scm->fp = DBUSCB(skb).fp;
  1428. +       skb->destructor = sock_wfree;
  1429. +       DBUSCB(skb).fp = NULL;
  1430. +
  1431. +       for (i = scm->fp->count-1; i >= 0; i--)
  1432. +               dbus_notinflight(scm->fp->fp[i]);
  1433. +}
  1434. +
  1435. +static void dbus_destruct_fds(struct sk_buff *skb)
  1436. +{
  1437. +       struct scm_cookie scm;
  1438. +       memset(&scm, 0, sizeof(scm));
  1439. +       dbus_detach_fds(&scm, skb);
  1440. +
  1441. +       /* Alas, it calls VFS */
  1442. +       /* So fscking what? fput() had been SMP-safe since the last Summer */
  1443. +       scm_destroy(&scm);
  1444. +       sock_wfree(skb);
  1445. +}
  1446. +
  1447. +static int dbus_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
  1448. +{
  1449. +       int i;
  1450. +
  1451. +       /*
  1452. +        * Need to duplicate file references for the sake of garbage
  1453. +        * collection.  Otherwise a socket in the fps might become a
  1454. +        * candidate for GC while the skb is not yet queued.
  1455. +        */
  1456. +       DBUSCB(skb).fp = scm_fp_dup(scm->fp);
  1457. +       if (!DBUSCB(skb).fp)
  1458. +               return -ENOMEM;
  1459. +
  1460. +       for (i = scm->fp->count-1; i >= 0; i--)
  1461. +               dbus_inflight(scm->fp->fp[i]);
  1462. +       skb->destructor = dbus_destruct_fds;
  1463. +       return 0;
  1464. +}
  1465. +
  1466. +/*
  1467. + *     Send AF_DBUS data.
  1468. + */
  1469. +
  1470. +struct delivery_data_t {
  1471. +       struct kiocb *kiocb;
  1472. +       struct msghdr *msg;
  1473. +       struct sk_buff *skb;
  1474. +       size_t len;
  1475. +};
  1476. +
  1477. +static void dbus_stream_deliver(struct sock *other, void *user_data)
  1478. +{
  1479. +       struct delivery_data_t *data = user_data;
  1480. +       struct kiocb *kiocb = data->kiocb;
  1481. +       struct msghdr *msg = data->msg;
  1482. +       size_t len = data->len;
  1483. +
  1484. +       int err;
  1485. +       struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
  1486. +       struct sk_buff *skb_cloned;
  1487. +       bool fds_sent = false;
  1488. +
  1489. +       if (other->sk_state != TCP_ESTABLISHED) {
  1490. +               pr_warning("D-Bus message delivery failure: non established socket!\n");
  1491. +               return;
  1492. +       }
  1493. +
  1494. +       skb_cloned = skb_clone(data->skb, GFP_KERNEL);
  1495. +       if (!skb_cloned) {
  1496. +               pr_warning("D-Bus message delivery failure: skb not cloned!\n");
  1497. +               err = -ENOMEM;
  1498. +               goto out_err;
  1499. +       }
  1500. +
  1501. +       memcpy(DBUSCREDS(skb_cloned), &siocb->scm->creds, sizeof(struct ucred));
  1502. +       /* Only send the fds in the first buffer */
  1503. +       if (siocb->scm->fp && !fds_sent) {
  1504. +               err = dbus_attach_fds(siocb->scm, skb_cloned);
  1505. +               if (err) {
  1506. +                       pr_warning("D-Bus message delivery failure: "
  1507. +                            "fds not attached!\n");
  1508. +                       kfree_skb(skb_cloned);
  1509. +                       goto out_err;
  1510. +               }
  1511. +               fds_sent = true;
  1512. +       }
  1513. +
  1514. +       dbus_state_lock(other);
  1515. +
  1516. +       if (sock_flag(other, SOCK_DEAD) ||
  1517. +           (other->sk_shutdown & RCV_SHUTDOWN))
  1518. +               goto pipe_err_free;
  1519. +
  1520. +       skb_queue_tail(&other->sk_receive_queue, skb_cloned);
  1521. +       dbus_state_unlock(other);
  1522. +       other->sk_data_ready(other, len);
  1523. +
  1524. +       return;
  1525. +
  1526. +pipe_err_free:
  1527. +       dbus_state_unlock(other);
  1528. +       kfree_skb(skb_cloned);
  1529. +
  1530. +       if (!(msg->msg_flags&MSG_NOSIGNAL))
  1531. +               send_sig(SIGPIPE, current, 0);
  1532. +       err = -EPIPE;
  1533. +out_err:
  1534. +       scm_destroy(siocb->scm);
  1535. +       siocb->scm = NULL;
  1536. +       return;
  1537. +}
  1538. +
  1539. +static int dbus_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
  1540. +                              struct msghdr *msg, size_t len)
  1541. +{
  1542. +       int sent = 0;
  1543. +       struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
  1544. +       struct sock *sk = sock->sk;
  1545. +       struct sock *other = dbus_peer(sk);
  1546. +       struct dbus_sock *otheru = dbus_sk(other);
  1547. +       struct hlist_node *other_node;
  1548. +       struct sockaddr_un *sunaddr = msg->msg_name;
  1549. +       int err;
  1550. +       struct scm_cookie tmp_scm;
  1551. +       struct DBusMessage dbus_message = {0,};
  1552. +       unsigned char *message = NULL;
  1553. +       int parsing_ret;
  1554. +       int main_recipient_found = 0;
  1555. +       struct sk_buff *skb;
  1556. +
  1557. +       pr_debug("D-Bus message received: %zd bytes\n", len);
  1558. +
  1559. +       if (NULL == siocb->scm)
  1560. +               siocb->scm = &tmp_scm;
  1561. +       wait_for_dbus_gc();
  1562. +       err = scm_send(sock, msg, siocb->scm);
  1563. +       if (err < 0)
  1564. +               return err;
  1565. +
  1566. +       err = -EOPNOTSUPP;
  1567. +       if (msg->msg_flags&MSG_OOB)
  1568. +               goto out_err;
  1569. +
  1570. +       if (msg->msg_namelen) {
  1571. +               err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP;
  1572. +               goto out_err;
  1573. +       } else {
  1574. +               sunaddr = NULL;
  1575. +               err = -ENOTCONN;
  1576. +               if (sk->sk_state != TCP_ESTABLISHED)
  1577. +                       goto out_err;
  1578. +       }
  1579. +
  1580. +       if (sk->sk_shutdown & SEND_SHUTDOWN)
  1581. +               goto pipe_err;
  1582. +
  1583. +       if (len > (8192 - 256)) {
  1584. +               pr_warning("Message too big, truncate\n");
  1585. +               len = 8192 - 256;
  1586. +       }
  1587. +
  1588. +       message = kmalloc(len, sk->sk_allocation);
  1589. +       if (!message) {
  1590. +               err = -ENOMEM;
  1591. +               goto out_err;
  1592. +       }
  1593. +       err = memcpy_fromiovecend(message, msg->msg_iov, 0, len);
  1594. +       if (err)
  1595. +               goto out_err;
  1596. +
  1597. +       /* We can parse the message*/
  1598. +       dbus_message.len = len;
  1599. +       dbus_message.new_len = len;
  1600. +       parsing_ret = dbus_message_parse(message, len, &dbus_message);
  1601. +
  1602. +       /* 'NameAcquired' signal for uniq name */
  1603. +       if (dbus_sk(sk)->daemon_side && parsing_ret == 0 &&
  1604. +            dbus_message.type == DBUS_MESSAGE_TYPE_SIGNAL &&
  1605. +            dbus_message.sender && dbus_message.path &&
  1606. +            dbus_message.interface && dbus_message.member &&
  1607. +           dbus_message.arg0 &&
  1608. +            !strcmp(dbus_message.sender, "org.freedesktop.DBus") &&
  1609. +            !strcmp(dbus_message.path, "/org/freedesktop/DBus") &&
  1610. +            !strcmp(dbus_message.interface, "org.freedesktop.DBus") &&
  1611. +            !strcmp(dbus_message.member, "NameAcquired")) {
  1612. +               if (dbus_message.arg0[0] == ':')
  1613. +                       dbus_bus_add_connection(otheru->bus, otheru,
  1614. +                               dbus_message.arg0);
  1615. +               else
  1616. +                       dbus_bus_add_well_known_name(otheru->bus, otheru,
  1617. +                               dbus_message.arg0);
  1618. +       }
  1619. +
  1620. +       /* 'NameLost' signal for well-known name */
  1621. +       if (dbus_sk(sk)->daemon_side && parsing_ret == 0 &&
  1622. +            dbus_message.type == DBUS_MESSAGE_TYPE_SIGNAL &&
  1623. +            dbus_message.sender && dbus_message.path &&
  1624. +            dbus_message.interface && dbus_message.member &&
  1625. +           dbus_message.arg0 && dbus_message.arg0[0] != ':' &&
  1626. +            !strcmp(dbus_message.sender, "org.freedesktop.DBus") &&
  1627. +            !strcmp(dbus_message.path, "/org/freedesktop/DBus") &&
  1628. +            !strcmp(dbus_message.interface, "org.freedesktop.DBus") &&
  1629. +            !strcmp(dbus_message.member, "NameLost")) {
  1630. +               if (dbus_message.arg0[0] == ':')
  1631. +                       dbus_bus_disconnected(otheru->bus, otheru);
  1632. +               else
  1633. +                       dbus_bus_remove_well_known_name(otheru->bus, otheru,
  1634. +                               dbus_message.arg0);
  1635. +       }
  1636. +
  1637. +       /* 'AddMatch' method call */
  1638. +       if (!dbus_sk(sk)->daemon_side && parsing_ret == 0 &&
  1639. +            dbus_message.type == DBUS_MESSAGE_TYPE_METHOD_CALL &&
  1640. +            dbus_message.destination && dbus_message.path &&
  1641. +            dbus_message.interface && dbus_message.member &&
  1642. +            !strcmp(dbus_message.destination, "org.freedesktop.DBus") &&
  1643. +            !strcmp(dbus_message.path, "/org/freedesktop/DBus") &&
  1644. +            !strcmp(dbus_message.interface, "org.freedesktop.DBus") &&
  1645. +            !strcmp(dbus_message.member, "AddMatch")) {
  1646. +               BusMatchRule *rule;
  1647. +               pr_debug("Add match rule \"%s\"\n", dbus_message.arg0);
  1648. +               rule = bus_match_rule_parse(dbus_sk(sk), dbus_message.arg0);
  1649. +               if (rule) {
  1650. +                       bus_matchmaker_add_rule(dbus_sk(sk)->bus->matchmaker, rule);
  1651. +                       pr_debug("Match rule added\n");
  1652. +               } else
  1653. +                       pr_warning("Match rule parsing failed\n");
  1654. +
  1655. +       }
  1656. +
  1657. +       /* Add a sender field */
  1658. +       if (!dbus_sk(sk)->daemon_side && parsing_ret == 0 &&
  1659. +            !dbus_message.sender && dbus_sk(sk)->uniq_name &&
  1660. +            (!dbus_message.destination ||
  1661. +             strcmp(dbus_message.destination, "org.freedesktop.DBus"))) {
  1662. +               dbus_message_add_sender(&dbus_message, dbus_sk(sk)->uniq_name,
  1663. +                    sk->sk_allocation);
  1664. +               message = dbus_message.message;
  1665. +       }
  1666. +
  1667. +       skb = sock_alloc_send_skb(sk, dbus_message.new_len,
  1668. +            msg->msg_flags&MSG_DONTWAIT, &err);
  1669. +
  1670. +       if (skb == NULL)
  1671. +               goto out_err;
  1672. +
  1673. +       if (skb_tailroom(skb) < dbus_message.new_len ||
  1674. +           dbus_message.new_len > ((sk->sk_sndbuf >> 1) - 64) ||
  1675. +           dbus_message.new_len > SKB_MAX_ALLOC) {
  1676. +               /* We don't split messages here */
  1677. +               pr_warning("D-Bus message too big (%zd) "
  1678. +                    "for sk_sndbuf=%d tail_room=%d SKB_MAX_ALLOC=%lu\n",
  1679. +                    dbus_message.new_len, sk->sk_sndbuf, skb_tailroom(skb), SKB_MAX_ALLOC);
  1680. +               kfree_skb(skb);
  1681. +               goto out_err;
  1682. +       }
  1683. +
  1684. +       memcpy(skb_put(skb, dbus_message.new_len), message,
  1685. +            dbus_message.new_len);
  1686. +
  1687. +       /* Delivery to the peer */
  1688. +       if (dbus_sk(sk)->daemon_side || parsing_ret != 0 ||
  1689. +            (dbus_message.destination &&
  1690. +             !strcmp(dbus_message.destination, "org.freedesktop.DBus"))) {
  1691. +               struct delivery_data_t data;
  1692. +               data.kiocb = kiocb;
  1693. +               data.msg = msg;
  1694. +                data.len = dbus_message.new_len;
  1695. +               data.skb = skb;
  1696. +               other = dbus_peer(sk);
  1697. +
  1698. +               if (dbus_sk(sk)->daemon_side)
  1699. +                       pr_debug("Message '%s' "
  1700. +                           "header '%s' -> '%s', "
  1701. +                           "routed [dbus-daemon] -> '%s'\n",
  1702. +                           dbus_message.member ? (char *)dbus_message.member : "(null)",
  1703. +                           dbus_message.sender ? (char *)dbus_message.sender : "(null)",
  1704. +                           dbus_message.destination ? (char *)dbus_message.destination : "(null)",
  1705. +                           (char *)(dbus_sk(other)->uniq_name) ?
  1706. +                           (char *)(dbus_sk(other)->uniq_name) : "(null)");
  1707. +               else
  1708. +                       pr_debug("Message '%s' "
  1709. +                           "header '%s' -> '%s', "
  1710. +                           "routed '%s' -> [dbus-daemon]\n",
  1711. +                           dbus_message.member ? (char *)dbus_message.member : "(null)",
  1712. +                           dbus_message.sender ? (char *)dbus_message.sender : "(null)",
  1713. +                           dbus_message.destination ? (char *)dbus_message.destination : "(null)",
  1714. +                           (char *)(dbus_sk(sk)->uniq_name) ?
  1715. +                           (char *)(dbus_sk(sk)->uniq_name) : "(null)");
  1716. +
  1717. +               dbus_stream_deliver(other, &data);
  1718. +               goto skip_kernel_routing;
  1719. +       }
  1720. +
  1721. +       /* Routed to the unique name or well-known name */
  1722. +       hlist_for_each_entry(otheru, other_node, &dbus_sk(sk)->bus->connections,
  1723. +            bus_link) {
  1724. +               struct delivery_data_t data;
  1725. +               int i, found = 0;
  1726. +               other = &otheru->sk;
  1727. +
  1728. +               if (other->sk_state != TCP_ESTABLISHED) {
  1729. +                       continue;
  1730. +               }
  1731. +               if (other == sk) {
  1732. +                       continue;
  1733. +               }
  1734. +               if (otheru->daemon_side) {
  1735. +                       continue;
  1736. +               }
  1737. +               if (!otheru->authenticated) {
  1738. +                       continue;
  1739. +               }
  1740. +               if (otheru->uniq_name == NULL ||
  1741. +                    dbus_message.destination == NULL) {
  1742. +                       continue;
  1743. +               }
  1744. +               if (!strcmp(otheru->uniq_name,
  1745. +                      dbus_message.destination)) {
  1746. +                       found = 1;
  1747. +               } else for (i = 0 ; i < MAX_WELL_KNOWN_NAMES ; i++) {
  1748. +                       char **name = &otheru->well_known_names[i];
  1749. +                       if (*name && dbus_message.destination &&
  1750. +                            !strcmp(*name, dbus_message.destination)) {
  1751. +                            found = 1;
  1752. +                            break;
  1753. +                       }
  1754. +               }
  1755. +               if (!found)
  1756. +                       continue;
  1757. +
  1758. +               pr_debug("Message '%s' "
  1759. +                    "header '%s' -> '%s', "
  1760. +                    "routed '%s' -> '%s'\n",
  1761. +                   dbus_message.member ? (char *)dbus_message.member : "(null)",
  1762. +                   dbus_message.sender ? (char *)dbus_message.sender : "(null)",
  1763. +                   dbus_message.destination ? (char *)dbus_message.destination : "(null)",
  1764. +                    (char *)(dbus_sk(sk)->uniq_name) ?
  1765. +                    (char *)(dbus_sk(sk)->uniq_name) : "(null)",
  1766. +                    (char *)(otheru->uniq_name) ?
  1767. +                    (char *)(otheru->uniq_name) : "(null)");
  1768. +
  1769. +               main_recipient_found = 1;
  1770. +
  1771. +               data.kiocb = kiocb;
  1772. +               data.msg = msg;
  1773. +               data.len = dbus_message.new_len;
  1774. +               data.skb = skb;
  1775. +               dbus_stream_deliver(other, &data);
  1776. +               break;
  1777. +       }
  1778. +
  1779. +       /* If we didn't find the destination, it is a D-Bus activation. D-Bus
  1780. +         * activation is done in userspace by dbus-daemon. */
  1781. +       if (!main_recipient_found && dbus_message.destination) {
  1782. +               struct delivery_data_t data;
  1783. +               data.kiocb = kiocb;
  1784. +               data.msg = msg;
  1785. +               data.len = dbus_message.new_len;
  1786. +               data.skb = skb;
  1787. +               other = dbus_peer(sk);
  1788. +
  1789. +               pr_debug("Message '%s' "
  1790. +                    "header '%s' -> '%s', "
  1791. +                    "routed '%s' -> [D-Bus activation]\n",
  1792. +                   dbus_message.member ? (char *)dbus_message.member : "(null)",
  1793. +                   dbus_message.sender ? (char *)dbus_message.sender : "(null)",
  1794. +                   dbus_message.destination ? (char *)dbus_message.destination : "(null)",
  1795. +                    (char *)(dbus_sk(sk)->uniq_name) ?
  1796. +                    (char *)(dbus_sk(sk)->uniq_name) : "(null)");
  1797. +
  1798. +               dbus_stream_deliver(other, &data);
  1799. +               goto skip_kernel_routing;
  1800. +       }
  1801. +
  1802. +       /* Generic delivery by match rules */
  1803. +       if (!dbus_sk(sk)->daemon_side && parsing_ret == 0) {
  1804. +               struct delivery_data_t data;
  1805. +               data.kiocb = kiocb;
  1806. +               data.msg = msg;
  1807. +               data.len = dbus_message.new_len;
  1808. +               data.skb = skb;
  1809. +
  1810. +               pr_debug("Message '%s' "
  1811. +                    "header '%s' -> '%s', "
  1812. +                    "routed '%s' -> [match rules]\n",
  1813. +                   dbus_message.member ? (char *)dbus_message.member : "(null)",
  1814. +                   dbus_message.sender ? (char *)dbus_message.sender : "(null)",
  1815. +                   dbus_message.destination ? (char *)dbus_message.destination : "(null)",
  1816. +                    (char *)(dbus_sk(sk)->uniq_name) ?
  1817. +                    (char *)(dbus_sk(sk)->uniq_name) : "(null)");
  1818. +
  1819. +               bus_matchmaker_get_recipients(dbus_sk(sk)->bus->matchmaker,
  1820. +                    dbus_sk(sk), NULL, &dbus_message, dbus_stream_deliver,
  1821. +                    &data);
  1822. +       }
  1823. +
  1824. +skip_kernel_routing:
  1825. +       kfree_skb(skb);
  1826. +       scm_destroy(siocb->scm);
  1827. +       siocb->scm = NULL;
  1828. +       kfree(message);
  1829. +
  1830. +       /* sent may be bigger than len but don't confuse userspace
  1831. +         * applications */
  1832. +       return len;
  1833. +
  1834. +pipe_err:
  1835. +       if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL))
  1836. +               send_sig(SIGPIPE, current, 0);
  1837. +       err = -EPIPE;
  1838. +out_err:
  1839. +       scm_destroy(siocb->scm);
  1840. +       siocb->scm = NULL;
  1841. +       if (message) {
  1842. +               kfree(message);
  1843. +       }
  1844. +       return sent ? : err;
  1845. +}
  1846. +
  1847. +static void dbus_copy_addr(struct msghdr *msg, struct sock *sk)
  1848. +{
  1849. +       struct dbus_sock *u = dbus_sk(sk);
  1850. +
  1851. +       msg->msg_namelen = 0;
  1852. +       if (u->addr) {
  1853. +               msg->msg_namelen = u->addr->len;
  1854. +               memcpy(msg->msg_name, u->addr->name, u->addr->len);
  1855. +       }
  1856. +}
  1857. +
  1858. +/*
  1859. + *     Sleep until data has arrive. But check for races..
  1860. + */
  1861. +
  1862. +static long dbus_stream_data_wait(struct sock *sk, long timeo)
  1863. +{
  1864. +       DEFINE_WAIT(wait);
  1865. +
  1866. +       dbus_state_lock(sk);
  1867. +
  1868. +       for (;;) {
  1869. +               prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
  1870. +
  1871. +               if (!skb_queue_empty(&sk->sk_receive_queue) ||
  1872. +                   sk->sk_err ||
  1873. +                   (sk->sk_shutdown & RCV_SHUTDOWN) ||
  1874. +                   signal_pending(current) ||
  1875. +                   !timeo)
  1876. +                       break;
  1877. +
  1878. +               set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
  1879. +               dbus_state_unlock(sk);
  1880. +               timeo = schedule_timeout(timeo);
  1881. +               dbus_state_lock(sk);
  1882. +               clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
  1883. +       }
  1884. +
  1885. +       finish_wait(sk_sleep(sk), &wait);
  1886. +       dbus_state_unlock(sk);
  1887. +       return timeo;
  1888. +}
  1889. +
  1890. +
  1891. +
  1892. +static int dbus_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
  1893. +                              struct msghdr *msg, size_t size,
  1894. +                              int flags)
  1895. +{
  1896. +       struct sock_iocb *siocb = kiocb_to_siocb(iocb);
  1897. +       struct scm_cookie tmp_scm;
  1898. +       struct sock *sk = sock->sk;
  1899. +       struct dbus_sock *u = dbus_sk(sk);
  1900. +       struct sockaddr_un *sunaddr = msg->msg_name;
  1901. +       int copied = 0;
  1902. +       int check_creds = 0;
  1903. +       int target;
  1904. +       int err = 0;
  1905. +       long timeo;
  1906. +
  1907. +       err = -EINVAL;
  1908. +       if (sk->sk_state != TCP_ESTABLISHED)
  1909. +               goto out;
  1910. +
  1911. +       err = -EOPNOTSUPP;
  1912. +       if (flags&MSG_OOB)
  1913. +               goto out;
  1914. +
  1915. +       target = sock_rcvlowat(sk, flags&MSG_WAITALL, size);
  1916. +       timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT);
  1917. +
  1918. +       msg->msg_namelen = 0;
  1919. +
  1920. +       /* Lock the socket to prevent queue disordering
  1921. +        * while sleeps in memcpy_tomsg
  1922. +        */
  1923. +
  1924. +       if (!siocb->scm) {
  1925. +               siocb->scm = &tmp_scm;
  1926. +               memset(&tmp_scm, 0, sizeof(tmp_scm));
  1927. +       }
  1928. +
  1929. +       mutex_lock(&u->readlock);
  1930. +
  1931. +       do {
  1932. +               int chunk;
  1933. +               struct sk_buff *skb;
  1934. +
  1935. +               dbus_state_lock(sk);
  1936. +               skb = skb_dequeue(&sk->sk_receive_queue);
  1937. +               if (skb == NULL) {
  1938. +                       if (copied >= target)
  1939. +                               goto unlock;
  1940. +
  1941. +                       /*
  1942. +                        *      POSIX 1003.1g mandates this order.
  1943. +                        */
  1944. +
  1945. +                       err = sock_error(sk);
  1946. +                       if (err)
  1947. +                               goto unlock;
  1948. +                       if (sk->sk_shutdown & RCV_SHUTDOWN)
  1949. +                               goto unlock;
  1950. +
  1951. +                       dbus_state_unlock(sk);
  1952. +                       err = -EAGAIN;
  1953. +                       if (!timeo)
  1954. +                               break;
  1955. +                       mutex_unlock(&u->readlock);
  1956. +
  1957. +                       timeo = dbus_stream_data_wait(sk, timeo);
  1958. +
  1959. +                       if (signal_pending(current)) {
  1960. +                               err = sock_intr_errno(timeo);
  1961. +                               goto out;
  1962. +                       }
  1963. +                       mutex_lock(&u->readlock);
  1964. +                       continue;
  1965. + unlock:
  1966. +                       dbus_state_unlock(sk);
  1967. +                       break;
  1968. +               }
  1969. +               dbus_state_unlock(sk);
  1970. +
  1971. +               if (check_creds) {
  1972. +                       /* Never glue messages from different writers */
  1973. +                       if (memcmp(DBUSCREDS(skb), &siocb->scm->creds,
  1974. +                                  sizeof(siocb->scm->creds)) != 0) {
  1975. +                               skb_queue_head(&sk->sk_receive_queue, skb);
  1976. +                               break;
  1977. +                       }
  1978. +               } else {
  1979. +                       /* Copy credentials */
  1980. +                       siocb->scm->creds = *DBUSCREDS(skb);
  1981. +                       check_creds = 1;
  1982. +               }
  1983. +
  1984. +               /* Copy address just once */
  1985. +               if (sunaddr) {
  1986. +                       dbus_copy_addr(msg, skb->sk);
  1987. +                       sunaddr = NULL;
  1988. +               }
  1989. +
  1990. +               chunk = min_t(unsigned int, skb->len, size);
  1991. +               if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
  1992. +                       skb_queue_head(&sk->sk_receive_queue, skb);
  1993. +                       if (copied == 0)
  1994. +                               copied = -EFAULT;
  1995. +                       break;
  1996. +               }
  1997. +               copied += chunk;
  1998. +               size -= chunk;
  1999. +
  2000. +               /* Mark read part of skb as used */
  2001. +               if (!(flags & MSG_PEEK)) {
  2002. +                       skb_pull(skb, chunk);
  2003. +
  2004. +                       if (DBUSCB(skb).fp)
  2005. +                               dbus_detach_fds(siocb->scm, skb);
  2006. +
  2007. +                       /* put the skb back if we didn't use it up.. */
  2008. +                       if (skb->len) {
  2009. +                               skb_queue_head(&sk->sk_receive_queue, skb);
  2010. +                               break;
  2011. +                       }
  2012. +
  2013. +                       kfree_skb(skb);
  2014. +
  2015. +                       if (siocb->scm->fp)
  2016. +                               break;
  2017. +               } else {
  2018. +                       /* It is questionable, see note in dbus_dgram_recvmsg.
  2019. +                         * FIXMEIM - dgram needed?
  2020. +                        */
  2021. +                       if (DBUSCB(skb).fp)
  2022. +                               siocb->scm->fp = scm_fp_dup(DBUSCB(skb).fp);
  2023. +
  2024. +                       /* put message back and return */
  2025. +                       skb_queue_head(&sk->sk_receive_queue, skb);
  2026. +                       break;
  2027. +               }
  2028. +       } while (size);
  2029. +
  2030. +       mutex_unlock(&u->readlock);
  2031. +       scm_recv(sock, msg, siocb->scm, flags);
  2032. +out:
  2033. +       return copied ? : err;
  2034. +}
  2035. +
  2036. +static int dbus_shutdown(struct socket *sock, int mode)
  2037. +{
  2038. +       struct sock *sk = sock->sk;
  2039. +       struct sock *other;
  2040. +
  2041. +       mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN);
  2042. +
  2043. +       if (mode) {
  2044. +               dbus_state_lock(sk);
  2045. +               sk->sk_shutdown |= mode;
  2046. +               other = dbus_peer(sk);
  2047. +               if (other)
  2048. +                       sock_hold(other);
  2049. +               dbus_state_unlock(sk);
  2050. +               sk->sk_state_change(sk);
  2051. +
  2052. +               if (other && (sk->sk_type == SOCK_STREAM)) {
  2053. +
  2054. +                       int peer_mode = 0;
  2055. +
  2056. +                       if (mode&RCV_SHUTDOWN)
  2057. +                               peer_mode |= SEND_SHUTDOWN;
  2058. +                       if (mode&SEND_SHUTDOWN)
  2059. +                               peer_mode |= RCV_SHUTDOWN;
  2060. +                       dbus_state_lock(other);
  2061. +                       other->sk_shutdown |= peer_mode;
  2062. +                       dbus_state_unlock(other);
  2063. +                       other->sk_state_change(other);
  2064. +                       if (peer_mode == SHUTDOWN_MASK)
  2065. +                               sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP);
  2066. +                       else if (peer_mode & RCV_SHUTDOWN)
  2067. +                               sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN);
  2068. +               }
  2069. +               if (other)
  2070. +                       sock_put(other);
  2071. +       }
  2072. +       return 0;
  2073. +}
  2074. +
  2075. +static int dbus_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
  2076. +{
  2077. +       struct sock *sk = sock->sk;
  2078. +       long amount = 0;
  2079. +       int err;
  2080. +
  2081. +       switch (cmd) {
  2082. +       case SIOCOUTQ: // TIOCOUTQ == 0x5411
  2083. +               amount = sk_wmem_alloc_get(sk);
  2084. +               err = put_user(amount, (int __user *)arg);
  2085. +               break;
  2086. +       case SIOCINQ: // FIONREAD == 0x541B
  2087. +               {
  2088. +                       struct sk_buff *skb;
  2089. +
  2090. +                       if (sk->sk_state == TCP_LISTEN) {
  2091. +                               err = -EINVAL;
  2092. +                               break;
  2093. +                       }
  2094. +
  2095. +                       spin_lock(&sk->sk_receive_queue.lock);
  2096. +                       if (sk->sk_type == SOCK_STREAM) {
  2097. +                               skb_queue_walk(&sk->sk_receive_queue, skb)
  2098. +                                       amount += skb->len;
  2099. +                       }
  2100. +                       spin_unlock(&sk->sk_receive_queue.lock);
  2101. +                       err = put_user(amount, (int __user *)arg);
  2102. +                       break;
  2103. +               }
  2104. +
  2105. +       case 0x5420:
  2106. +               pr_debug("D-Bus ioctl 0x5420 -> returns 42\n");
  2107. +               amount = 42;
  2108. +               err = put_user(amount, (int __user *)arg);
  2109. +               break;
  2110. +       default:
  2111. +               err = -ENOIOCTLCMD;
  2112. +               break;
  2113. +       }
  2114. +       return err;
  2115. +}
  2116. +
  2117. +static unsigned int dbus_poll(struct file *file, struct socket *sock, poll_table *wait)
  2118. +{
  2119. +       struct sock *sk = sock->sk;
  2120. +       unsigned int mask;
  2121. +
  2122. +       sock_poll_wait(file, sk_sleep(sk), wait);
  2123. +       mask = 0;
  2124. +
  2125. +       /* exceptional events? */
  2126. +       if (sk->sk_err)
  2127. +               mask |= POLLERR;
  2128. +       if (sk->sk_shutdown == SHUTDOWN_MASK)
  2129. +               mask |= POLLHUP;
  2130. +       if (sk->sk_shutdown & RCV_SHUTDOWN)
  2131. +               mask |= POLLRDHUP;
  2132. +
  2133. +       /* readable? */
  2134. +       if (!skb_queue_empty(&sk->sk_receive_queue) ||
  2135. +           (sk->sk_shutdown & RCV_SHUTDOWN))
  2136. +               mask |= POLLIN | POLLRDNORM;
  2137. +
  2138. +       /* Connection-based need to check for termination and startup */
  2139. +       if ((sk->sk_type == SOCK_STREAM) &&
  2140. +           sk->sk_state == TCP_CLOSE)
  2141. +               mask |= POLLHUP;
  2142. +
  2143. +       /*
  2144. +        * we set writable also when the other side has shut down the
  2145. +        * connection. This prevents stuck sockets.
  2146. +        */
  2147. +       if (dbus_writable(sk))
  2148. +               mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
  2149. +
  2150. +       return mask;
  2151. +}
  2152. +
  2153. +#ifdef CONFIG_PROC_FS
  2154. +static struct sock *first_dbus_socket(int *i)
  2155. +{
  2156. +       for (*i = 0; *i <= DBUS_HASH_SIZE; (*i)++) {
  2157. +               if (!hlist_empty(&dbus_socket_table[*i]))
  2158. +                       return __sk_head(&dbus_socket_table[*i]);
  2159. +       }
  2160. +       return NULL;
  2161. +}
  2162. +
  2163. +static struct sock *next_dbus_socket(int *i, struct sock *s)
  2164. +{
  2165. +       struct sock *next = sk_next(s);
  2166. +       /* More in this chain? */
  2167. +       if (next)
  2168. +               return next;
  2169. +       /* Look for next non-empty chain. */
  2170. +       for ((*i)++; *i <= DBUS_HASH_SIZE; (*i)++) {
  2171. +               if (!hlist_empty(&dbus_socket_table[*i]))
  2172. +                       return __sk_head(&dbus_socket_table[*i]);
  2173. +       }
  2174. +       return NULL;
  2175. +}
  2176. +
  2177. +struct dbus_iter_state {
  2178. +       struct seq_net_private p;
  2179. +       int i;
  2180. +};
  2181. +
  2182. +static struct sock *dbus_seq_idx(struct seq_file *seq, loff_t pos)
  2183. +{
  2184. +       struct dbus_iter_state *iter = seq->private;
  2185. +       loff_t off = 0;
  2186. +       struct sock *s;
  2187. +
  2188. +       for (s = first_dbus_socket(&iter->i); s; s = next_dbus_socket(&iter->i, s)) {
  2189. +               if (sock_net(s) != seq_file_net(seq))
  2190. +                       continue;
  2191. +               if (off == pos)
  2192. +                       return s;
  2193. +               ++off;
  2194. +       }
  2195. +       return NULL;
  2196. +}
  2197. +
  2198. +static void *dbus_seq_start(struct seq_file *seq, loff_t *pos)
  2199. +       __acquires(dbus_table_lock)
  2200. +{
  2201. +       spin_lock(&dbus_table_lock);
  2202. +       return *pos ? dbus_seq_idx(seq, *pos - 1) : SEQ_START_TOKEN;
  2203. +}
  2204. +
  2205. +static void *dbus_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  2206. +{
  2207. +       struct dbus_iter_state *iter = seq->private;
  2208. +       struct sock *sk = v;
  2209. +       ++*pos;
  2210. +
  2211. +       if (v == SEQ_START_TOKEN)
  2212. +               sk = first_dbus_socket(&iter->i);
  2213. +       else
  2214. +               sk = next_dbus_socket(&iter->i, sk);
  2215. +       while (sk && (sock_net(sk) != seq_file_net(seq)))
  2216. +               sk = next_dbus_socket(&iter->i, sk);
  2217. +       return sk;
  2218. +}
  2219. +
  2220. +static void dbus_seq_stop(struct seq_file *seq, void *v)
  2221. +       __releases(dbus_table_lock)
  2222. +{
  2223. +       spin_unlock(&dbus_table_lock);
  2224. +}
  2225. +
  2226. +static int dbus_seq_show(struct seq_file *seq, void *v)
  2227. +{
  2228. +
  2229. +       if (v == SEQ_START_TOKEN)
  2230. +               seq_puts(seq, "Num       RefCount Protocol Flags    Type St "
  2231. +                        "Inode Path\n");
  2232. +       else {
  2233. +               struct sock *s = v;
  2234. +               struct dbus_sock *u = dbus_sk(s);
  2235. +               dbus_state_lock(s);
  2236. +
  2237. +               seq_printf(seq, "%p: %08X %08X %08X %04X %02X %5lu",
  2238. +                       s,
  2239. +                       atomic_read(&s->sk_refcnt),
  2240. +                       0,
  2241. +                       s->sk_state == TCP_LISTEN ? __SO_ACCEPTCON : 0,
  2242. +                       s->sk_type,
  2243. +                       s->sk_socket ?
  2244. +                       (s->sk_state == TCP_ESTABLISHED ? SS_CONNECTED : SS_UNCONNECTED) :
  2245. +                       (s->sk_state == TCP_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING),
  2246. +                       sock_i_ino(s));
  2247. +
  2248. +               if (u->addr) {
  2249. +                       int i, len;
  2250. +                       seq_putc(seq, ' ');
  2251. +
  2252. +                       i = 0;
  2253. +                       len = u->addr->len - sizeof(short);
  2254. +                       if (!DBUS_ABSTRACT(s))
  2255. +                               len--;
  2256. +                       else {
  2257. +                               seq_putc(seq, '@');
  2258. +                               i++;
  2259. +                       }
  2260. +                       for ( ; i < len; i++)
  2261. +                               seq_putc(seq, u->addr->name->sun_path[i]);
  2262. +               }
  2263. +               dbus_state_unlock(s);
  2264. +               seq_putc(seq, '\n');
  2265. +       }
  2266. +
  2267. +       return 0;
  2268. +}
  2269. +
  2270. +static const struct seq_operations dbus_seq_ops = {
  2271. +       .start  = dbus_seq_start,
  2272. +       .next   = dbus_seq_next,
  2273. +       .stop   = dbus_seq_stop,
  2274. +       .show   = dbus_seq_show,
  2275. +};
  2276. +
  2277. +static int dbus_seq_open(struct inode *inode, struct file *file)
  2278. +{
  2279. +       return seq_open_net(inode, file, &dbus_seq_ops,
  2280. +                           sizeof(struct dbus_iter_state));
  2281. +}
  2282. +
  2283. +static const struct file_operations dbus_seq_fops = {
  2284. +       .owner          = THIS_MODULE,
  2285. +       .open           = dbus_seq_open,
  2286. +       .read           = seq_read,
  2287. +       .llseek         = seq_lseek,
  2288. +       .release        = seq_release_net,
  2289. +};
  2290. +
  2291. +#endif
  2292. +
  2293. +static const struct net_proto_family dbus_family_ops = {
  2294. +       .family = PF_DBUS,
  2295. +       .create = dbus_create,
  2296. +       .owner  = THIS_MODULE,
  2297. +};
  2298. +
  2299. +
  2300. +static int dbus_net_init(struct net *net)
  2301. +{
  2302. +       int error = -ENOMEM;
  2303. +
  2304. +       net->unx.sysctl_max_dgram_qlen = 10;
  2305. +       if (dbus_sysctl_register(net))
  2306. +               goto out;
  2307. +
  2308. +#ifdef CONFIG_PROC_FS
  2309. +       if (!proc_net_fops_create(net, "dbus", 0, &dbus_seq_fops)) {
  2310. +               dbus_sysctl_unregister(net);
  2311. +               goto out;
  2312. +       }
  2313. +#endif
  2314. +       error = 0;
  2315. +out:
  2316. +       return error;
  2317. +}
  2318. +
  2319. +static void dbus_net_exit(struct net *net)
  2320. +{
  2321. +       dbus_sysctl_unregister(net);
  2322. +       proc_net_remove(net, "dbus");
  2323. +}
  2324. +
  2325. +static struct pernet_operations dbus_net_ops = {
  2326. +       .init = dbus_net_init,
  2327. +       .exit = dbus_net_exit,
  2328. +};
  2329. +
  2330. +static int __init af_dbus_init(void)
  2331. +{
  2332. +       int rc = -1;
  2333. +       struct sk_buff *dummy_skb;
  2334. +
  2335. +       BUILD_BUG_ON(sizeof(struct dbus_skb_parms) > sizeof(dummy_skb->cb));
  2336. +
  2337. +       rc = proto_register(&dbus_proto, 1);
  2338. +       if (rc != 0) {
  2339. +               printk(KERN_CRIT "%s: Cannot create dbus_sock SLAB cache!\n",
  2340. +                      __func__);
  2341. +               goto out;
  2342. +       }
  2343. +
  2344. +       sock_register(&dbus_family_ops);
  2345. +       register_pernet_subsys(&dbus_net_ops);
  2346. +out:
  2347. +       return rc;
  2348. +}
  2349. +
  2350. +static void __exit af_dbus_exit(void)
  2351. +{
  2352. +       sock_unregister(PF_DBUS);
  2353. +       proto_unregister(&dbus_proto);
  2354. +       unregister_pernet_subsys(&dbus_net_ops);
  2355. +}
  2356. +
  2357. +/* Earlier than device_initcall() so that other drivers invoking
  2358. +   request_module() don't end up in a loop when modprobe tries
  2359. +   to use a DBUS socket. But later than subsys_initcall() because
  2360. +   we depend on stuff initialised there */
  2361. +fs_initcall(af_dbus_init);
  2362. +module_exit(af_dbus_exit);
  2363. +
  2364. +MODULE_LICENSE("GPL");
  2365. +MODULE_ALIAS_NETPROTO(PF_DBUS);
  2366. diff --git a/net/dbus/bus.c b/net/dbus/bus.c
  2367. new file mode 100644
  2368. index 0000000..1da98a6
  2369. --- /dev/null
  2370. +++ b/net/dbus/bus.c
  2371. @@ -0,0 +1,91 @@
  2372. +/* bus.c  The D-Bus bus
  2373. + *
  2374. + * Copyright (C) 2010  Collabora Ltd
  2375. + * Authors:    Alban Crequy <alban.crequy@collabora.co.uk>
  2376. + *
  2377. + * This program is free software; you can redistribute it and/or modify
  2378. + * it under the terms of the GNU General Public License as published by
  2379. + * the Free Software Foundation; either version 2 of the License, or
  2380. + * (at your option) any later version.
  2381. + *
  2382. + * This program is distributed in the hope that it will be useful,
  2383. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2384. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  2385. + * GNU General Public License for more details.
  2386. + *
  2387. + * You should have received a copy of the GNU General Public License
  2388. + * along with this program; if not, write to the Free Software
  2389. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  2390. + *
  2391. + */
  2392. +
  2393. +#include "bus.h"
  2394. +#include "dbus-protocol.h"
  2395. +
  2396. +struct DBusBus *
  2397. +dbus_bus_new (void)
  2398. +{
  2399. +       struct DBusBus *bus = kmalloc(sizeof(struct DBusBus), GFP_KERNEL);
  2400. +       INIT_HLIST_HEAD(&bus->connections);
  2401. +       return bus;
  2402. +}
  2403. +
  2404. +void
  2405. +dbus_bus_free (struct DBusBus *bus)
  2406. +{
  2407. +       kfree(bus);
  2408. +}
  2409. +
  2410. +void
  2411. +dbus_bus_add_connection (struct DBusBus *bus, struct dbus_sock *conn,
  2412. +    const char *unique_name)
  2413. +{
  2414. +       BUG_ON(!unique_name);
  2415. +       BUG_ON(unique_name[0] != ':');
  2416. +
  2417. +       conn->authenticated = 1;
  2418. +       conn->uniq_name =
  2419. +          kmalloc(strlen(unique_name)+1, GFP_KERNEL);
  2420. +       strcpy(conn->uniq_name, unique_name);
  2421. +
  2422. +       hlist_add_head(&conn->bus_link, &bus->connections);
  2423. +}
  2424. +
  2425. +void
  2426. +dbus_bus_disconnected(struct DBusBus *bus, struct dbus_sock *conn)
  2427. +{
  2428. +       if (!bus)
  2429. +               return;
  2430. +
  2431. +       hlist_del_init(&conn->bus_link);
  2432. +}
  2433. +
  2434. +void
  2435. +dbus_bus_add_well_known_name (struct DBusBus *bus,
  2436. +    struct dbus_sock *conn, const char *name)
  2437. +{
  2438. +       int i;
  2439. +       for (i = 0 ; i < MAX_WELL_KNOWN_NAMES ; i++) {
  2440. +               char **nameptr = &conn->well_known_names[i];
  2441. +               if (!*nameptr) {
  2442. +                    *nameptr = kstrdup(name, GFP_KERNEL);
  2443. +                    break;
  2444. +               }
  2445. +       }
  2446. +}
  2447. +
  2448. +void
  2449. +dbus_bus_remove_well_known_name (struct DBusBus *bus,
  2450. +    struct dbus_sock *conn, const char *name)
  2451. +{
  2452. +       int i;
  2453. +       for (i = 0 ; i < MAX_WELL_KNOWN_NAMES ; i++) {
  2454. +               char **nameptr = &conn->well_known_names[i];
  2455. +               if (*nameptr && name &&
  2456. +                   !strcmp(name, *nameptr)) {
  2457. +                    kfree(*nameptr);
  2458. +                    *nameptr = NULL;
  2459. +                    break;
  2460. +               }
  2461. +       }
  2462. +}
  2463. diff --git a/net/dbus/bus.h b/net/dbus/bus.h
  2464. new file mode 100644
  2465. index 0000000..88100f6
  2466. --- /dev/null
  2467. +++ b/net/dbus/bus.h
  2468. @@ -0,0 +1,45 @@
  2469. +/* bus.h  The D-Bus Bus
  2470. + *
  2471. + * Copyright (C) 2010  Collabora Ltd
  2472. + *
  2473. + * This program is free software; you can redistribute it and/or modify
  2474. + * it under the terms of the GNU General Public License as published by
  2475. + * the Free Software Foundation; either version 2 of the License, or
  2476. + * (at your option) any later version.
  2477. + *
  2478. + * This program is distributed in the hope that it will be useful,
  2479. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2480. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  2481. + * GNU General Public License for more details.
  2482. + *
  2483. + * You should have received a copy of the GNU General Public License
  2484. + * along with this program; if not, write to the Free Software
  2485. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  2486. + *
  2487. + */
  2488. +
  2489. +#ifndef DBUS_BUS_H
  2490. +#define DBUS_BUS_H
  2491. +
  2492. +#include <net/af_dbus.h>
  2493. +#include "matchrule.h"
  2494. +
  2495. +struct DBusBus {
  2496. +       struct hlist_head connections;
  2497. +       BusMatchmaker* matchmaker;
  2498. +};
  2499. +
  2500. +
  2501. +struct DBusBus *dbus_bus_new (void);
  2502. +void dbus_bus_free (struct DBusBus *bus);
  2503. +
  2504. +void dbus_bus_add_connection (struct DBusBus *bus, struct dbus_sock  *conn,
  2505. +    const char *unique_name);
  2506. +void dbus_bus_disconnected(struct DBusBus *bus, struct dbus_sock  *conn);
  2507. +
  2508. +void dbus_bus_add_well_known_name (struct DBusBus *bus,
  2509. +    struct dbus_sock *conn, const char *name);
  2510. +void dbus_bus_remove_well_known_name (struct DBusBus *bus,
  2511. +    struct dbus_sock *conn, const char *name);
  2512. +
  2513. +#endif /* DBUS_BUS_H */
  2514. diff --git a/net/dbus/dbus-protocol.h b/net/dbus/dbus-protocol.h
  2515. new file mode 100644
  2516. index 0000000..17798e9
  2517. --- /dev/null
  2518. +++ b/net/dbus/dbus-protocol.h
  2519. @@ -0,0 +1,462 @@
  2520. +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
  2521. +/* dbus-protocol.h  D-Bus protocol constants
  2522. + *
  2523. + * Copyright (C) 2002, 2003  CodeFactory AB
  2524. + * Copyright (C) 2004, 2005 Red Hat, Inc.
  2525. + *
  2526. + * Licensed under the Academic Free License version 2.1
  2527. + *
  2528. + * This program is free software; you can redistribute it and/or modify
  2529. + * it under the terms of the GNU General Public License as published by
  2530. + * the Free Software Foundation; either version 2 of the License, or
  2531. + * (at your option) any later version.
  2532. + *
  2533. + * This program is distributed in the hope that it will be useful,
  2534. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2535. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  2536. + * GNU General Public License for more details.
  2537. + *
  2538. + * You should have received a copy of the GNU General Public License
  2539. + * along with this program; if not, write to the Free Software
  2540. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  2541. + *
  2542. + */
  2543. +
  2544. +#ifndef DBUS_PROTOCOL_H
  2545. +#define DBUS_PROTOCOL_H
  2546. +
  2547. +/* Don't include anything in here from anywhere else. It's
  2548. + * intended for use by any random library.
  2549. + */
  2550. +
  2551. +#ifdef  __cplusplus
  2552. +extern "C" {
  2553. +#if 0
  2554. +} /* avoids confusing emacs indentation */
  2555. +#endif
  2556. +#endif
  2557. +
  2558. +/* Normally docs are in .c files, but there isn't a .c file for this. */
  2559. +/**
  2560. + * @defgroup DBusProtocol Protocol constants
  2561. + * @ingroup  DBus
  2562. + *
  2563. + * @brief Defines constants which are part of the D-Bus protocol
  2564. + *
  2565. + * This header is intended for use by any library, not only libdbus.
  2566. + *
  2567. + * @{
  2568. + */
  2569. +
  2570. +
  2571. +/* Message byte order */
  2572. +#define DBUS_LITTLE_ENDIAN ('l')  /**< Code marking LSB-first byte order in the wire protocol. */
  2573. +#define DBUS_BIG_ENDIAN    ('B')  /**< Code marking MSB-first byte order in the wire protocol. */
  2574. +
  2575. +/** Protocol version. */
  2576. +#define DBUS_MAJOR_PROTOCOL_VERSION 1
  2577. +
  2578. +/** Type code that is never equal to a legitimate type code */
  2579. +#define DBUS_TYPE_INVALID       ((int) '\0')
  2580. +/** #DBUS_TYPE_INVALID as a string literal instead of a int literal */
  2581. +#define DBUS_TYPE_INVALID_AS_STRING        "\0"
  2582. +
  2583. +/* Primitive types */
  2584. +/** Type code marking an 8-bit unsigned integer */
  2585. +#define DBUS_TYPE_BYTE          ((int) 'y')
  2586. +/** #DBUS_TYPE_BYTE as a string literal instead of a int literal */
  2587. +#define DBUS_TYPE_BYTE_AS_STRING           "y"
  2588. +/** Type code marking a boolean */
  2589. +#define DBUS_TYPE_BOOLEAN       ((int) 'b')
  2590. +/** #DBUS_TYPE_BOOLEAN as a string literal instead of a int literal */
  2591. +#define DBUS_TYPE_BOOLEAN_AS_STRING        "b"
  2592. +/** Type code marking a 16-bit signed integer */
  2593. +#define DBUS_TYPE_INT16         ((int) 'n')
  2594. +/** #DBUS_TYPE_INT16 as a string literal instead of a int literal */
  2595. +#define DBUS_TYPE_INT16_AS_STRING          "n"
  2596. +/** Type code marking a 16-bit unsigned integer */
  2597. +#define DBUS_TYPE_UINT16        ((int) 'q')
  2598. +/** #DBUS_TYPE_UINT16 as a string literal instead of a int literal */
  2599. +#define DBUS_TYPE_UINT16_AS_STRING         "q"
  2600. +/** Type code marking a 32-bit signed integer */
  2601. +#define DBUS_TYPE_INT32         ((int) 'i')
  2602. +/** #DBUS_TYPE_INT32 as a string literal instead of a int literal */
  2603. +#define DBUS_TYPE_INT32_AS_STRING          "i"
  2604. +/** Type code marking a 32-bit unsigned integer */
  2605. +#define DBUS_TYPE_UINT32        ((int) 'u')
  2606. +/** #DBUS_TYPE_UINT32 as a string literal instead of a int literal */
  2607. +#define DBUS_TYPE_UINT32_AS_STRING         "u"
  2608. +/** Type code marking a 64-bit signed integer */
  2609. +#define DBUS_TYPE_INT64         ((int) 'x')
  2610. +/** #DBUS_TYPE_INT64 as a string literal instead of a int literal */
  2611. +#define DBUS_TYPE_INT64_AS_STRING          "x"
  2612. +/** Type code marking a 64-bit unsigned integer */
  2613. +#define DBUS_TYPE_UINT64        ((int) 't')
  2614. +/** #DBUS_TYPE_UINT64 as a string literal instead of a int literal */
  2615. +#define DBUS_TYPE_UINT64_AS_STRING         "t"
  2616. +/** Type code marking an 8-byte double in IEEE 754 format */
  2617. +#define DBUS_TYPE_DOUBLE        ((int) 'd')
  2618. +/** #DBUS_TYPE_DOUBLE as a string literal instead of a int literal */
  2619. +#define DBUS_TYPE_DOUBLE_AS_STRING         "d"
  2620. +/** Type code marking a UTF-8 encoded, nul-terminated Unicode string */
  2621. +#define DBUS_TYPE_STRING        ((int) 's')
  2622. +/** #DBUS_TYPE_STRING as a string literal instead of a int literal */
  2623. +#define DBUS_TYPE_STRING_AS_STRING         "s"
  2624. +/** Type code marking a D-Bus object path */
  2625. +#define DBUS_TYPE_OBJECT_PATH   ((int) 'o')
  2626. +/** #DBUS_TYPE_OBJECT_PATH as a string literal instead of a int literal */
  2627. +#define DBUS_TYPE_OBJECT_PATH_AS_STRING    "o"
  2628. +/** Type code marking a D-Bus type signature */
  2629. +#define DBUS_TYPE_SIGNATURE     ((int) 'g')
  2630. +/** #DBUS_TYPE_SIGNATURE as a string literal instead of a int literal */
  2631. +#define DBUS_TYPE_SIGNATURE_AS_STRING      "g"
  2632. +/** Type code marking a unix file descriptor */
  2633. +#define DBUS_TYPE_UNIX_FD      ((int) 'h')
  2634. +/** #DBUS_TYPE_UNIX_FD as a string literal instead of a int literal */
  2635. +#define DBUS_TYPE_UNIX_FD_AS_STRING        "h"
  2636. +
  2637. +/* Compound types */
  2638. +/** Type code marking a D-Bus array type */
  2639. +#define DBUS_TYPE_ARRAY         ((int) 'a')
  2640. +/** #DBUS_TYPE_ARRAY as a string literal instead of a int literal */
  2641. +#define DBUS_TYPE_ARRAY_AS_STRING          "a"
  2642. +/** Type code marking a D-Bus variant type */
  2643. +#define DBUS_TYPE_VARIANT       ((int) 'v')
  2644. +/** #DBUS_TYPE_VARIANT as a string literal instead of a int literal */
  2645. +#define DBUS_TYPE_VARIANT_AS_STRING        "v"
  2646. +
  2647. +/** STRUCT and DICT_ENTRY are sort of special since their codes can't
  2648. + * appear in a type string, instead
  2649. + * DBUS_STRUCT_BEGIN_CHAR/DBUS_DICT_ENTRY_BEGIN_CHAR have to appear
  2650. + */
  2651. +/** Type code used to represent a struct; however, this type code does not appear
  2652. + * in type signatures, instead #DBUS_STRUCT_BEGIN_CHAR and #DBUS_STRUCT_END_CHAR will
  2653. + * appear in a signature.
  2654. + */
  2655. +#define DBUS_TYPE_STRUCT        ((int) 'r')
  2656. +/** #DBUS_TYPE_STRUCT as a string literal instead of a int literal */
  2657. +#define DBUS_TYPE_STRUCT_AS_STRING         "r"
  2658. +/** Type code used to represent a dict entry; however, this type code does not appear
  2659. + * in type signatures, instead #DBUS_DICT_ENTRY_BEGIN_CHAR and #DBUS_DICT_ENTRY_END_CHAR will
  2660. + * appear in a signature.
  2661. + */
  2662. +#define DBUS_TYPE_DICT_ENTRY    ((int) 'e')
  2663. +/** #DBUS_TYPE_DICT_ENTRY as a string literal instead of a int literal */
  2664. +#define DBUS_TYPE_DICT_ENTRY_AS_STRING     "e"
  2665. +
  2666. +/** Does not include #DBUS_TYPE_INVALID, #DBUS_STRUCT_BEGIN_CHAR, #DBUS_STRUCT_END_CHAR,
  2667. + * #DBUS_DICT_ENTRY_BEGIN_CHAR, or #DBUS_DICT_ENTRY_END_CHAR - i.e. it is the number of
  2668. + * valid types, not the number of distinct characters that may appear in a type signature.
  2669. + */
  2670. +#define DBUS_NUMBER_OF_TYPES    (16)
  2671. +
  2672. +/* characters other than typecodes that appear in type signatures */
  2673. +
  2674. +/** Code marking the start of a struct type in a type signature */
  2675. +#define DBUS_STRUCT_BEGIN_CHAR   ((int) '(')
  2676. +/** #DBUS_STRUCT_BEGIN_CHAR as a string literal instead of a int literal */
  2677. +#define DBUS_STRUCT_BEGIN_CHAR_AS_STRING   "("
  2678. +/** Code marking the end of a struct type in a type signature */
  2679. +#define DBUS_STRUCT_END_CHAR     ((int) ')')
  2680. +/** #DBUS_STRUCT_END_CHAR a string literal instead of a int literal */
  2681. +#define DBUS_STRUCT_END_CHAR_AS_STRING     ")"
  2682. +/** Code marking the start of a dict entry type in a type signature */
  2683. +#define DBUS_DICT_ENTRY_BEGIN_CHAR   ((int) '{')
  2684. +/** #DBUS_DICT_ENTRY_BEGIN_CHAR as a string literal instead of a int literal */
  2685. +#define DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING   "{"
  2686. +/** Code marking the end of a dict entry type in a type signature */
  2687. +#define DBUS_DICT_ENTRY_END_CHAR     ((int) '}')
  2688. +/** #DBUS_DICT_ENTRY_END_CHAR as a string literal instead of a int literal */
  2689. +#define DBUS_DICT_ENTRY_END_CHAR_AS_STRING     "}"
  2690. +
  2691. +/** Max length in bytes of a bus name, interface, or member (not object
  2692. + * path, paths are unlimited). This is limited because lots of stuff
  2693. + * is O(n) in this number, plus it would be obnoxious to type in a
  2694. + * paragraph-long method name so most likely something like that would
  2695. + * be an exploit.
  2696. + */
  2697. +#define DBUS_MAXIMUM_NAME_LENGTH 255
  2698. +
  2699. +/** This one is 255 so it fits in a byte */
  2700. +#define DBUS_MAXIMUM_SIGNATURE_LENGTH 255
  2701. +
  2702. +/** Max length of a match rule string; to keep people from hosing the
  2703. + * daemon with some huge rule
  2704. + */
  2705. +#define DBUS_MAXIMUM_MATCH_RULE_LENGTH 1024
  2706. +
  2707. +/** Max arg number you can match on in a match rule, e.g.
  2708. + * arg0='hello' is OK, arg3489720987='hello' is not
  2709. + */
  2710. +#define DBUS_MAXIMUM_MATCH_RULE_ARG_NUMBER 63
  2711. +  
  2712. +/** Max length of a marshaled array in bytes (64M, 2^26) We use signed
  2713. + * int for lengths so must be INT_MAX or less.  We need something a
  2714. + * bit smaller than INT_MAX because the array is inside a message with
  2715. + * header info, etc.  so an INT_MAX array wouldn't allow the message
  2716. + * overhead.  The 64M number is an attempt at a larger number than
  2717. + * we'd reasonably ever use, but small enough that your bus would chew
  2718. + * through it fairly quickly without locking up forever. If you have
  2719. + * data that's likely to be larger than this, you should probably be
  2720. + * sending it in multiple incremental messages anyhow.
  2721. + */
  2722. +#define DBUS_MAXIMUM_ARRAY_LENGTH (67108864)
  2723. +/** Number of bits you need in an unsigned to store the max array size */
  2724. +#define DBUS_MAXIMUM_ARRAY_LENGTH_BITS 26
  2725. +
  2726. +/** The maximum total message size including header and body; similar
  2727. + * rationale to max array size.
  2728. + */
  2729. +#define DBUS_MAXIMUM_MESSAGE_LENGTH (DBUS_MAXIMUM_ARRAY_LENGTH * 2)
  2730. +/** Number of bits you need in an unsigned to store the max message size */
  2731. +#define DBUS_MAXIMUM_MESSAGE_LENGTH_BITS 27
  2732. +
  2733. +/** The maximum total number of unix fds in a message. Similar
  2734. + * rationale as DBUS_MAXIMUM_MESSAGE_LENGTH. However we divide by four
  2735. + * given that one fd is an int and hence at least 32 bits.
  2736. + */
  2737. +#define DBUS_MAXIMUM_MESSAGE_UNIX_FDS (DBUS_MAXIMUM_MESSAGE_LENGTH/4)
  2738. +/** Number of bits you need in an unsigned to store the max message unix fds */
  2739. +#define DBUS_MAXIMUM_MESSAGE_UNIX_FDS_BITS (DBUS_MAXIMUM_MESSAGE_LENGTH_BITS-2)
  2740. +
  2741. +/** Depth of recursion in the type tree. This is automatically limited
  2742. + * to DBUS_MAXIMUM_SIGNATURE_LENGTH since you could only have an array
  2743. + * of array of array of ... that fit in the max signature.  But that's
  2744. + * probably a bit too large.
  2745. + */
  2746. +#define DBUS_MAXIMUM_TYPE_RECURSION_DEPTH 32
  2747. +
  2748. +/* Types of message */
  2749. +
  2750. +/** This value is never a valid message type, see dbus_message_get_type() */
  2751. +#define DBUS_MESSAGE_TYPE_INVALID       0
  2752. +/** Message type of a method call message, see dbus_message_get_type() */
  2753. +#define DBUS_MESSAGE_TYPE_METHOD_CALL   1
  2754. +/** Message type of a method return message, see dbus_message_get_type() */
  2755. +#define DBUS_MESSAGE_TYPE_METHOD_RETURN 2
  2756. +/** Message type of an error reply message, see dbus_message_get_type() */
  2757. +#define DBUS_MESSAGE_TYPE_ERROR         3
  2758. +/** Message type of a signal message, see dbus_message_get_type() */
  2759. +#define DBUS_MESSAGE_TYPE_SIGNAL        4
  2760. +
  2761. +#define DBUS_NUM_MESSAGE_TYPES          5
  2762. +
  2763. +/* Header flags */
  2764. +
  2765. +/** If set, this flag means that the sender of a message does not care about getting
  2766. + * a reply, so the recipient need not send one. See dbus_message_set_no_reply().
  2767. + */
  2768. +#define DBUS_HEADER_FLAG_NO_REPLY_EXPECTED 0x1
  2769. +/**
  2770. + * If set, this flag means that even if the message bus knows how to start an owner for
  2771. + * the destination bus name (see dbus_message_set_destination()), it should not
  2772. + * do so. If this flag is not set, the bus may launch a program to process the
  2773. + * message.
  2774. + */
  2775. +#define DBUS_HEADER_FLAG_NO_AUTO_START     0x2
  2776. +
  2777. +/* Header fields */
  2778. +
  2779. +/** Not equal to any valid header field code */
  2780. +#define DBUS_HEADER_FIELD_INVALID        0
  2781. +/** Header field code for the path - the path is the object emitting a signal or the object receiving a method call.
  2782. + * See dbus_message_set_path().
  2783. + */
  2784. +#define DBUS_HEADER_FIELD_PATH           1
  2785. +/** Header field code for the interface containing a member (method or signal).
  2786. + * See dbus_message_set_interface().
  2787. + */
  2788. +#define DBUS_HEADER_FIELD_INTERFACE      2
  2789. +/** Header field code for a member (method or signal). See dbus_message_set_member(). */
  2790. +#define DBUS_HEADER_FIELD_MEMBER         3
  2791. +/** Header field code for an error name (found in #DBUS_MESSAGE_TYPE_ERROR messages).
  2792. + * See dbus_message_set_error_name().
  2793. + */
  2794. +#define DBUS_HEADER_FIELD_ERROR_NAME     4
  2795. +/** Header field code for a reply serial, used to match a #DBUS_MESSAGE_TYPE_METHOD_RETURN message with the
  2796. + * message that it's a reply to. See dbus_message_set_reply_serial().
  2797. + */
  2798. +#define DBUS_HEADER_FIELD_REPLY_SERIAL   5
  2799. +/**
  2800. + * Header field code for the destination bus name of a message. See dbus_message_set_destination().
  2801. + */
  2802. +#define DBUS_HEADER_FIELD_DESTINATION    6
  2803. +/**
  2804. + * Header field code for the sender of a message; usually initialized by the message bus.
  2805. + * See dbus_message_set_sender().
  2806. + */
  2807. +#define DBUS_HEADER_FIELD_SENDER         7
  2808. +/**
  2809. + * Header field code for the type signature of a message.
  2810. + */
  2811. +#define DBUS_HEADER_FIELD_SIGNATURE      8
  2812. +/**
  2813. + * Header field code for the number of unix file descriptors associated
  2814. + * with this message.
  2815. + */
  2816. +#define DBUS_HEADER_FIELD_UNIX_FDS       9
  2817. +
  2818. +
  2819. +/**
  2820. + * Value of the highest-numbered header field code, can be used to determine
  2821. + * the size of an array indexed by header field code. Remember though
  2822. + * that unknown codes must be ignored, so check for that before
  2823. + * indexing the array.
  2824. + */
  2825. +#define DBUS_HEADER_FIELD_LAST DBUS_HEADER_FIELD_UNIX_FDS
  2826. +
  2827. +/** Header format is defined as a signature:
  2828. + *   byte                            byte order
  2829. + *   byte                            message type ID
  2830. + *   byte                            flags
  2831. + *   byte                            protocol version
  2832. + *   uint32                          body length
  2833. + *   uint32                          serial
  2834. + *   array of struct (byte,variant)  (field name, value)
  2835. + *
  2836. + * The length of the header can be computed as the
  2837. + * fixed size of the initial data, plus the length of
  2838. + * the array at the end, plus padding to an 8-boundary.
  2839. + */
  2840. +#define DBUS_HEADER_SIGNATURE                   \
  2841. +     DBUS_TYPE_BYTE_AS_STRING                   \
  2842. +     DBUS_TYPE_BYTE_AS_STRING                   \
  2843. +     DBUS_TYPE_BYTE_AS_STRING                   \
  2844. +     DBUS_TYPE_BYTE_AS_STRING                   \
  2845. +     DBUS_TYPE_UINT32_AS_STRING                 \
  2846. +     DBUS_TYPE_UINT32_AS_STRING                 \
  2847. +     DBUS_TYPE_ARRAY_AS_STRING                  \
  2848. +     DBUS_STRUCT_BEGIN_CHAR_AS_STRING           \
  2849. +     DBUS_TYPE_BYTE_AS_STRING                   \
  2850. +     DBUS_TYPE_VARIANT_AS_STRING                \
  2851. +     DBUS_STRUCT_END_CHAR_AS_STRING
  2852. +
  2853. +
  2854. +/**
  2855. + * The smallest header size that can occur.  (It won't be valid due to
  2856. + * missing required header fields.) This is 4 bytes, two uint32, an
  2857. + * array length. This isn't any kind of resource limit, just the
  2858. + * necessary/logical outcome of the header signature.
  2859. + */
  2860. +#define DBUS_MINIMUM_HEADER_SIZE 16
  2861. +
  2862. +/* Errors */
  2863. +/* WARNING these get autoconverted to an enum in dbus-glib.h. Thus,
  2864. + * if you change the order it breaks the ABI. Keep them in order.
  2865. + * Also, don't change the formatting since that will break the sed
  2866. + * script.
  2867. + */
  2868. +/** A generic error; "something went wrong" - see the error message for more. */
  2869. +#define DBUS_ERROR_FAILED                     "org.freedesktop.DBus.Error.Failed"
  2870. +/** There was not enough memory to complete an operation. */
  2871. +#define DBUS_ERROR_NO_MEMORY                  "org.freedesktop.DBus.Error.NoMemory"
  2872. +/** The bus doesn't know how to launch a service to supply the bus name you wanted. */
  2873. +#define DBUS_ERROR_SERVICE_UNKNOWN            "org.freedesktop.DBus.Error.ServiceUnknown"
  2874. +/** The bus name you referenced doesn't exist (i.e. no application owns it). */
  2875. +#define DBUS_ERROR_NAME_HAS_NO_OWNER          "org.freedesktop.DBus.Error.NameHasNoOwner"
  2876. +/** No reply to a message expecting one, usually means a timeout occurred. */
  2877. +#define DBUS_ERROR_NO_REPLY                   "org.freedesktop.DBus.Error.NoReply"
  2878. +/** Something went wrong reading or writing to a socket, for example. */
  2879. +#define DBUS_ERROR_IO_ERROR                   "org.freedesktop.DBus.Error.IOError"
  2880. +/** A D-Bus bus address was malformed. */
  2881. +#define DBUS_ERROR_BAD_ADDRESS                "org.freedesktop.DBus.Error.BadAddress"
  2882. +/** Requested operation isn't supported (like ENOSYS on UNIX). */
  2883. +#define DBUS_ERROR_NOT_SUPPORTED              "org.freedesktop.DBus.Error.NotSupported"
  2884. +/** Some limited resource is exhausted. */
  2885. +#define DBUS_ERROR_LIMITS_EXCEEDED            "org.freedesktop.DBus.Error.LimitsExceeded"
  2886. +/** Security restrictions don't allow doing what you're trying to do. */
  2887. +#define DBUS_ERROR_ACCESS_DENIED              "org.freedesktop.DBus.Error.AccessDenied"
  2888. +/** Authentication didn't work. */
  2889. +#define DBUS_ERROR_AUTH_FAILED                "org.freedesktop.DBus.Error.AuthFailed"
  2890. +/** Unable to connect to server (probably caused by ECONNREFUSED on a socket). */
  2891. +#define DBUS_ERROR_NO_SERVER                  "org.freedesktop.DBus.Error.NoServer"
  2892. +/** Certain timeout errors, possibly ETIMEDOUT on a socket.
  2893. + * Note that #DBUS_ERROR_NO_REPLY is used for message reply timeouts.
  2894. + * @warning this is confusingly-named given that #DBUS_ERROR_TIMED_OUT also exists. We can't fix
  2895. + * it for compatibility reasons so just be careful.
  2896. + */
  2897. +#define DBUS_ERROR_TIMEOUT                    "org.freedesktop.DBus.Error.Timeout"
  2898. +/** No network access (probably ENETUNREACH on a socket). */
  2899. +#define DBUS_ERROR_NO_NETWORK                 "org.freedesktop.DBus.Error.NoNetwork"
  2900. +/** Can't bind a socket since its address is in use (i.e. EADDRINUSE). */
  2901. +#define DBUS_ERROR_ADDRESS_IN_USE             "org.freedesktop.DBus.Error.AddressInUse"
  2902. +/** The connection is disconnected and you're trying to use it. */
  2903. +#define DBUS_ERROR_DISCONNECTED               "org.freedesktop.DBus.Error.Disconnected"
  2904. +/** Invalid arguments passed to a method call. */
  2905. +#define DBUS_ERROR_INVALID_ARGS               "org.freedesktop.DBus.Error.InvalidArgs"
  2906. +/** Missing file. */
  2907. +#define DBUS_ERROR_FILE_NOT_FOUND             "org.freedesktop.DBus.Error.FileNotFound"
  2908. +/** Existing file and the operation you're using does not silently overwrite. */
  2909. +#define DBUS_ERROR_FILE_EXISTS                "org.freedesktop.DBus.Error.FileExists"
  2910. +/** Method name you invoked isn't known by the object you invoked it on. */
  2911. +#define DBUS_ERROR_UNKNOWN_METHOD             "org.freedesktop.DBus.Error.UnknownMethod"
  2912. +/** Certain timeout errors, e.g. while starting a service.
  2913. + * @warning this is confusingly-named given that #DBUS_ERROR_TIMEOUT also exists. We can't fix
  2914. + * it for compatibility reasons so just be careful.
  2915. + */
  2916. +#define DBUS_ERROR_TIMED_OUT                  "org.freedesktop.DBus.Error.TimedOut"
  2917. +/** Tried to remove or modify a match rule that didn't exist. */
  2918. +#define DBUS_ERROR_MATCH_RULE_NOT_FOUND       "org.freedesktop.DBus.Error.MatchRuleNotFound"
  2919. +/** The match rule isn't syntactically valid. */
  2920. +#define DBUS_ERROR_MATCH_RULE_INVALID         "org.freedesktop.DBus.Error.MatchRuleInvalid"
  2921. +/** While starting a new process, the exec() call failed. */
  2922. +#define DBUS_ERROR_SPAWN_EXEC_FAILED          "org.freedesktop.DBus.Error.Spawn.ExecFailed"
  2923. +/** While starting a new process, the fork() call failed. */
  2924. +#define DBUS_ERROR_SPAWN_FORK_FAILED          "org.freedesktop.DBus.Error.Spawn.ForkFailed"
  2925. +/** While starting a new process, the child exited with a status code. */
  2926. +#define DBUS_ERROR_SPAWN_CHILD_EXITED         "org.freedesktop.DBus.Error.Spawn.ChildExited"
  2927. +/** While starting a new process, the child exited on a signal. */
  2928. +#define DBUS_ERROR_SPAWN_CHILD_SIGNALED       "org.freedesktop.DBus.Error.Spawn.ChildSignaled"
  2929. +/** While starting a new process, something went wrong. */
  2930. +#define DBUS_ERROR_SPAWN_FAILED               "org.freedesktop.DBus.Error.Spawn.Failed"
  2931. +/** We failed to setup the environment correctly. */
  2932. +#define DBUS_ERROR_SPAWN_SETUP_FAILED         "org.freedesktop.DBus.Error.Spawn.FailedToSetup"
  2933. +/** We failed to setup the config parser correctly. */
  2934. +#define DBUS_ERROR_SPAWN_CONFIG_INVALID       "org.freedesktop.DBus.Error.Spawn.ConfigInvalid"
  2935. +/** Bus name was not valid. */
  2936. +#define DBUS_ERROR_SPAWN_SERVICE_INVALID      "org.freedesktop.DBus.Error.Spawn.ServiceNotValid"
  2937. +/** Service file not found in system-services directory. */
  2938. +#define DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND    "org.freedesktop.DBus.Error.Spawn.ServiceNotFound"
  2939. +/** Permissions are incorrect on the setuid helper. */
  2940. +#define DBUS_ERROR_SPAWN_PERMISSIONS_INVALID  "org.freedesktop.DBus.Error.Spawn.PermissionsInvalid"
  2941. +/** Service file invalid (Name, User or Exec missing). */
  2942. +#define DBUS_ERROR_SPAWN_FILE_INVALID         "org.freedesktop.DBus.Error.Spawn.FileInvalid"
  2943. +/** Tried to get a UNIX process ID and it wasn't available. */
  2944. +#define DBUS_ERROR_SPAWN_NO_MEMORY            "org.freedesktop.DBus.Error.Spawn.NoMemory"
  2945. +/** Tried to get a UNIX process ID and it wasn't available. */
  2946. +#define DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN    "org.freedesktop.DBus.Error.UnixProcessIdUnknown"
  2947. +/** A type signature is not valid. */
  2948. +#define DBUS_ERROR_INVALID_SIGNATURE          "org.freedesktop.DBus.Error.InvalidSignature"
  2949. +/** A file contains invalid syntax or is otherwise broken. */
  2950. +#define DBUS_ERROR_INVALID_FILE_CONTENT       "org.freedesktop.DBus.Error.InvalidFileContent"
  2951. +/** Asked for SELinux security context and it wasn't available. */
  2952. +#define DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN    "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"
  2953. +/** Asked for ADT audit data and it wasn't available. */
  2954. +#define DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN     "org.freedesktop.DBus.Error.AdtAuditDataUnknown"
  2955. +/** There's already an object with the requested object path. */
  2956. +#define DBUS_ERROR_OBJECT_PATH_IN_USE         "org.freedesktop.DBus.Error.ObjectPathInUse"
  2957. +/** The message meta data does not match the payload. e.g. expected
  2958. +    number of file descriptors were not sent over the socket this message was received on. */
  2959. +#define DBUS_ERROR_INCONSISTENT_MESSAGE       "org.freedesktop.DBus.Error.InconsistentMessage"
  2960. +
  2961. +/* XML introspection format */
  2962. +
  2963. +/** XML namespace of the introspection format version 1.0 */
  2964. +#define DBUS_INTROSPECT_1_0_XML_NAMESPACE         "http://www.freedesktop.org/standards/dbus"
  2965. +/** XML public identifier of the introspection format version 1.0 */
  2966. +#define DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
  2967. +/** XML system identifier of the introspection format version 1.0 */
  2968. +#define DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"
  2969. +/** XML document type declaration of the introspection format version 1.0 */
  2970. +#define DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE "<!DOCTYPE node PUBLIC \""DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER"\"\n\""DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER"\">\n"
  2971. +
  2972. +/** @} */
  2973. +
  2974. +#ifdef __cplusplus
  2975. +#if 0
  2976. +{ /* avoids confusing emacs indentation */
  2977. +#endif
  2978. +}
  2979. +#endif
  2980. +
  2981. +#endif /* DBUS_PROTOCOL_H */
  2982. diff --git a/net/dbus/garbage.c b/net/dbus/garbage.c
  2983. new file mode 100644
  2984. index 0000000..dee0a41
  2985. --- /dev/null
  2986. +++ b/net/dbus/garbage.c
  2987. @@ -0,0 +1,389 @@
  2988. +/*
  2989. + * NET3:       Garbage Collector For AF_DBUS sockets
  2990. + *
  2991. + * Garbage Collector:
  2992. + *     Copyright (C) Barak A. Pearlmutter.
  2993. + *     Released under the GPL version 2 or later.
  2994. + *
  2995. + * Chopped about by Alan Cox 22/3/96 to make it fit the AF_UNIX socket problem.
  2996. + * If it doesn't work blame me, it worked when Barak sent it.
  2997. + *
  2998. + * Assumptions:
  2999. + *
  3000. + *  - object w/ a bit
  3001. + *  - free list
  3002. + *
  3003. + * Current optimizations:
  3004. + *
  3005. + *  - explicit stack instead of recursion
  3006. + *  - tail recurse on first born instead of immediate push/pop
  3007. + *  - we gather the stuff that should not be killed into tree
  3008. + *    and stack is just a path from root to the current pointer.
  3009. + *
  3010. + *  Future optimizations:
  3011. + *
  3012. + *  - don't just push entire root set; process in place
  3013. + *
  3014. + *     This program is free software; you can redistribute it and/or
  3015. + *     modify it under the terms of the GNU General Public License
  3016. + *     as published by the Free Software Foundation; either version
  3017. + *     2 of the License, or (at your option) any later version.
  3018. + *
  3019. + *  Fixes:
  3020. + *     Alan Cox        07 Sept 1997    Vmalloc internal stack as needed.
  3021. + *                                     Cope with changing max_files.
  3022. + *     Al Viro         11 Oct 1998
  3023. + *             Graph may have cycles. That is, we can send the descriptor
  3024. + *             of foo to bar and vice versa. Current code chokes on that.
  3025. + *             Fix: move SCM_RIGHTS ones into the separate list and then
  3026. + *             skb_free() them all instead of doing explicit fput's.
  3027. + *             Another problem: since fput() may block somebody may
  3028. + *             create a new unix_socket when we are in the middle of sweep
  3029. + *             phase. Fix: revert the logic wrt MARKED. Mark everything
  3030. + *             upon the beginning and unmark non-junk ones.
  3031. + *
  3032. + *             [12 Oct 1998] AAARGH! New code purges all SCM_RIGHTS
  3033. + *             sent to connect()'ed but still not accept()'ed sockets.
  3034. + *             Fixed. Old code had slightly different problem here:
  3035. + *             extra fput() in situation when we passed the descriptor via
  3036. + *             such socket and closed it (descriptor). That would happen on
  3037. + *             each unix_gc() until the accept(). Since the struct file in
  3038. + *             question would go to the free list and might be reused...
  3039. + *             That might be the reason of random oopses on filp_close()
  3040. + *             in unrelated processes.
  3041. + *
  3042. + *     AV              28 Feb 1999
  3043. + *             Kill the explicit allocation of stack. Now we keep the tree
  3044. + *             with root in dummy + pointer (gc_current) to one of the nodes.
  3045. + *             Stack is represented as path from gc_current to dummy. Unmark
  3046. + *             now means "add to tree". Push == "make it a son of gc_current".
  3047. + *             Pop == "move gc_current to parent". We keep only pointers to
  3048. + *             parents (->gc_tree).
  3049. + *     AV              1 Mar 1999
  3050. + *             Damn. Added missing check for ->dead in listen queues scanning.
  3051. + *
  3052. + *     Miklos Szeredi 25 Jun 2007
  3053. + *             Reimplement with a cycle collecting algorithm. This should
  3054. + *             solve several problems with the previous code, like being racy
  3055. + *             wrt receive and holding up unrelated socket operations.
  3056. + */
  3057. +
  3058. +#include <linux/kernel.h>
  3059. +#include <linux/string.h>
  3060. +#include <linux/socket.h>
  3061. +#include <linux/un.h>
  3062. +#include <linux/net.h>
  3063. +#include <linux/fs.h>
  3064. +#include <linux/slab.h>
  3065. +#include <linux/skbuff.h>
  3066. +#include <linux/netdevice.h>
  3067. +#include <linux/file.h>
  3068. +#include <linux/proc_fs.h>
  3069. +#include <linux/mutex.h>
  3070. +#include <linux/wait.h>
  3071. +
  3072. +#include <net/sock.h>
  3073. +#include <net/af_dbus.h>
  3074. +#include <net/scm.h>
  3075. +#include <net/tcp_states.h>
  3076. +
  3077. +/* Internal data structures and random procedures: */
  3078. +
  3079. +static LIST_HEAD(gc_inflight_list);
  3080. +static LIST_HEAD(gc_candidates);
  3081. +static DEFINE_SPINLOCK(dbus_gc_lock);
  3082. +static DECLARE_WAIT_QUEUE_HEAD(dbus_gc_wait);
  3083. +
  3084. +unsigned int dbus_tot_inflight;
  3085. +
  3086. +
  3087. +static struct sock *dbus_get_socket(struct file *filp)
  3088. +{
  3089. +       struct sock *u_sock = NULL;
  3090. +       struct inode *inode = filp->f_path.dentry->d_inode;
  3091. +
  3092. +       /*
  3093. +        *      Socket ?
  3094. +        */
  3095. +       if (S_ISSOCK(inode->i_mode)) {
  3096. +               struct socket *sock = SOCKET_I(inode);
  3097. +               struct sock *s = sock->sk;
  3098. +
  3099. +               /*
  3100. +                *      PF_DBUS ?
  3101. +                */
  3102. +               if (s && sock->ops && sock->ops->family == PF_DBUS)
  3103. +                       u_sock = s;
  3104. +       }
  3105. +       return u_sock;
  3106. +}
  3107. +
  3108. +/*
  3109. + *     Keep the number of times in flight count for the file
  3110. + *     descriptor if it is for an AF_DBUS socket.
  3111. + */
  3112. +
  3113. +void dbus_inflight(struct file *fp)
  3114. +{
  3115. +       struct sock *s = dbus_get_socket(fp);
  3116. +       if (s) {
  3117. +               struct dbus_sock *u = dbus_sk(s);
  3118. +               spin_lock(&dbus_gc_lock);
  3119. +               if (atomic_long_inc_return(&u->inflight) == 1) {
  3120. +                       BUG_ON(!list_empty(&u->link));
  3121. +                       list_add_tail(&u->link, &gc_inflight_list);
  3122. +               } else {
  3123. +                       BUG_ON(list_empty(&u->link));
  3124. +               }
  3125. +               dbus_tot_inflight++;
  3126. +               spin_unlock(&dbus_gc_lock);
  3127. +       }
  3128. +}
  3129. +
  3130. +void dbus_notinflight(struct file *fp)
  3131. +{
  3132. +       struct sock *s = dbus_get_socket(fp);
  3133. +       if (s) {
  3134. +               struct dbus_sock *u = dbus_sk(s);
  3135. +               spin_lock(&dbus_gc_lock);
  3136. +               BUG_ON(list_empty(&u->link));
  3137. +               if (atomic_long_dec_and_test(&u->inflight))
  3138. +                       list_del_init(&u->link);
  3139. +               dbus_tot_inflight--;
  3140. +               spin_unlock(&dbus_gc_lock);
  3141. +       }
  3142. +}
  3143. +
  3144. +static inline struct sk_buff *sock_queue_head(struct sock *sk)
  3145. +{
  3146. +       return (struct sk_buff *)&sk->sk_receive_queue;
  3147. +}
  3148. +
  3149. +#define receive_queue_for_each_skb(sk, next, skb) \
  3150. +       for (skb = sock_queue_head(sk)->next, next = skb->next; \
  3151. +            skb != sock_queue_head(sk); skb = next, next = skb->next)
  3152. +
  3153. +static void scan_inflight(struct sock *x, void (*func)(struct dbus_sock *),
  3154. +                         struct sk_buff_head *hitlist)
  3155. +{
  3156. +       struct sk_buff *skb;
  3157. +       struct sk_buff *next;
  3158. +
  3159. +       spin_lock(&x->sk_receive_queue.lock);
  3160. +       receive_queue_for_each_skb(x, next, skb) {
  3161. +               /*
  3162. +                *      Do we have file descriptors ?
  3163. +                */
  3164. +               if (DBUSCB(skb).fp) {
  3165. +                       bool hit = false;
  3166. +                       /*
  3167. +                        *      Process the descriptors of this socket
  3168. +                        */
  3169. +                       int nfd = DBUSCB(skb).fp->count;
  3170. +                       struct file **fp = DBUSCB(skb).fp->fp;
  3171. +                       while (nfd--) {
  3172. +                               /*
  3173. +                                *      Get the socket the fd matches
  3174. +                                *      if it indeed does so
  3175. +                                */
  3176. +                               struct sock *sk = dbus_get_socket(*fp++);
  3177. +                               if (sk) {
  3178. +                                       struct dbus_sock *u = dbus_sk(sk);
  3179. +
  3180. +                                       /*
  3181. +                                        * Ignore non-candidates, they could
  3182. +                                        * have been added to the queues after
  3183. +                                        * starting the garbage collection
  3184. +                                        */
  3185. +                                       if (u->gc_candidate) {
  3186. +                                               hit = true;
  3187. +                                               func(u);
  3188. +                                       }
  3189. +                               }
  3190. +                       }
  3191. +                       if (hit && hitlist != NULL) {
  3192. +                               __skb_unlink(skb, &x->sk_receive_queue);
  3193. +                               __skb_queue_tail(hitlist, skb);
  3194. +                       }
  3195. +               }
  3196. +       }
  3197. +       spin_unlock(&x->sk_receive_queue.lock);
  3198. +}
  3199. +
  3200. +static void scan_children(struct sock *x, void (*func)(struct dbus_sock *),
  3201. +                         struct sk_buff_head *hitlist)
  3202. +{
  3203. +       if (x->sk_state != TCP_LISTEN)
  3204. +               scan_inflight(x, func, hitlist);
  3205. +       else {
  3206. +               struct sk_buff *skb;
  3207. +               struct sk_buff *next;
  3208. +               struct dbus_sock *u;
  3209. +               LIST_HEAD(embryos);
  3210. +
  3211. +               /*
  3212. +                * For a listening socket collect the queued embryos
  3213. +                * and perform a scan on them as well.
  3214. +                */
  3215. +               spin_lock(&x->sk_receive_queue.lock);
  3216. +               receive_queue_for_each_skb(x, next, skb) {
  3217. +                       u = dbus_sk(skb->sk);
  3218. +
  3219. +                       /*
  3220. +                        * An embryo cannot be in-flight, so it's safe
  3221. +                        * to use the list link.
  3222. +                        */
  3223. +                       BUG_ON(!list_empty(&u->link));
  3224. +                       list_add_tail(&u->link, &embryos);
  3225. +               }
  3226. +               spin_unlock(&x->sk_receive_queue.lock);
  3227. +
  3228. +               while (!list_empty(&embryos)) {
  3229. +                       u = list_entry(embryos.next, struct dbus_sock, link);
  3230. +                       scan_inflight(&u->sk, func, hitlist);
  3231. +                       list_del_init(&u->link);
  3232. +               }
  3233. +       }
  3234. +}
  3235. +
  3236. +static void dec_inflight(struct dbus_sock *usk)
  3237. +{
  3238. +       atomic_long_dec(&usk->inflight);
  3239. +}
  3240. +
  3241. +static void inc_inflight(struct dbus_sock *usk)
  3242. +{
  3243. +       atomic_long_inc(&usk->inflight);
  3244. +}
  3245. +
  3246. +static void inc_inflight_move_tail(struct dbus_sock *u)
  3247. +{
  3248. +       atomic_long_inc(&u->inflight);
  3249. +       /*
  3250. +        * If this still might be part of a cycle, move it to the end
  3251. +        * of the list, so that it's checked even if it was already
  3252. +        * passed over
  3253. +        */
  3254. +       if (u->gc_maybe_cycle)
  3255. +               list_move_tail(&u->link, &gc_candidates);
  3256. +}
  3257. +
  3258. +static bool gc_in_progress = false;
  3259. +
  3260. +void wait_for_dbus_gc(void)
  3261. +{
  3262. +       wait_event(dbus_gc_wait, gc_in_progress == false);
  3263. +}
  3264. +
  3265. +/* The external entry point: dbus_gc() */
  3266. +void dbus_gc(void)
  3267. +{
  3268. +       struct dbus_sock *u;
  3269. +       struct dbus_sock *next;
  3270. +       struct sk_buff_head hitlist;
  3271. +       struct list_head cursor;
  3272. +       LIST_HEAD(not_cycle_list);
  3273. +
  3274. +       spin_lock(&dbus_gc_lock);
  3275. +
  3276. +       /* Avoid a recursive GC. */
  3277. +       if (gc_in_progress)
  3278. +               goto out;
  3279. +
  3280. +       gc_in_progress = true;
  3281. +       /*
  3282. +        * First, select candidates for garbage collection.  Only
  3283. +        * in-flight sockets are considered, and from those only ones
  3284. +        * which don't have any external reference.
  3285. +        *
  3286. +        * Holding dbus_gc_lock will protect these candidates from
  3287. +        * being detached, and hence from gaining an external
  3288. +        * reference.  Since there are no possible receivers, all
  3289. +        * buffers currently on the candidates' queues stay there
  3290. +        * during the garbage collection.
  3291. +        *
  3292. +        * We also know that no new candidate can be added onto the
  3293. +        * receive queues.  Other, non candidate sockets _can_ be
  3294. +        * added to queue, so we must make sure only to touch
  3295. +        * candidates.
  3296. +        */
  3297. +       list_for_each_entry_safe(u, next, &gc_inflight_list, link) {
  3298. +               long total_refs;
  3299. +               long inflight_refs;
  3300. +
  3301. +               total_refs = file_count(u->sk.sk_socket->file);
  3302. +               inflight_refs = atomic_long_read(&u->inflight);
  3303. +
  3304. +               BUG_ON(inflight_refs < 1);
  3305. +               BUG_ON(total_refs < inflight_refs);
  3306. +               if (total_refs == inflight_refs) {
  3307. +                       list_move_tail(&u->link, &gc_candidates);
  3308. +                       u->gc_candidate = 1;
  3309. +                       u->gc_maybe_cycle = 1;
  3310. +               }
  3311. +       }
  3312. +
  3313. +       /*
  3314. +        * Now remove all internal in-flight reference to children of
  3315. +        * the candidates.
  3316. +        */
  3317. +       list_for_each_entry(u, &gc_candidates, link)
  3318. +               scan_children(&u->sk, dec_inflight, NULL);
  3319. +
  3320. +       /*
  3321. +        * Restore the references for children of all candidates,
  3322. +        * which have remaining references.  Do this recursively, so
  3323. +        * only those remain, which form cyclic references.
  3324. +        *
  3325. +        * Use a "cursor" link, to make the list traversal safe, even
  3326. +        * though elements might be moved about.
  3327. +        */
  3328. +       list_add(&cursor, &gc_candidates);
  3329. +       while (cursor.next != &gc_candidates) {
  3330. +               u = list_entry(cursor.next, struct dbus_sock, link);
  3331. +
  3332. +               /* Move cursor to after the current position. */
  3333. +               list_move(&cursor, &u->link);
  3334. +
  3335. +               if (atomic_long_read(&u->inflight) > 0) {
  3336. +                       list_move_tail(&u->link, &not_cycle_list);
  3337. +                       u->gc_maybe_cycle = 0;
  3338. +                       scan_children(&u->sk, inc_inflight_move_tail, NULL);
  3339. +               }
  3340. +       }
  3341. +       list_del(&cursor);
  3342. +
  3343. +       /*
  3344. +        * not_cycle_list contains those sockets which do not make up a
  3345. +        * cycle.  Restore these to the inflight list.
  3346. +        */
  3347. +       while (!list_empty(&not_cycle_list)) {
  3348. +               u = list_entry(not_cycle_list.next, struct dbus_sock, link);
  3349. +               u->gc_candidate = 0;
  3350. +               list_move_tail(&u->link, &gc_inflight_list);
  3351. +       }
  3352. +
  3353. +       /*
  3354. +        * Now gc_candidates contains only garbage.  Restore original
  3355. +        * inflight counters for these as well, and remove the skbuffs
  3356. +        * which are creating the cycle(s).
  3357. +        */
  3358. +       skb_queue_head_init(&hitlist);
  3359. +       list_for_each_entry(u, &gc_candidates, link)
  3360. +       scan_children(&u->sk, inc_inflight, &hitlist);
  3361. +
  3362. +       spin_unlock(&dbus_gc_lock);
  3363. +
  3364. +       /* Here we are. Hitlist is filled. Die. */
  3365. +       __skb_queue_purge(&hitlist);
  3366. +
  3367. +       spin_lock(&dbus_gc_lock);
  3368. +
  3369. +       /* All candidates should have been detached by now. */
  3370. +       BUG_ON(!list_empty(&gc_candidates));
  3371. +       gc_in_progress = false;
  3372. +       wake_up(&dbus_gc_wait);
  3373. +
  3374. + out:
  3375. +       spin_unlock(&dbus_gc_lock);
  3376. +}
  3377. diff --git a/net/dbus/matchrule.c b/net/dbus/matchrule.c
  3378. new file mode 100644
  3379. index 0000000..52ebd6b
  3380. --- /dev/null
  3381. +++ b/net/dbus/matchrule.c
  3382. @@ -0,0 +1,1651 @@
  3383. +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
  3384. +/* matchrule.c  D-Bus match rule implementation
  3385. + *
  3386. + * Based on signals.c from dbus
  3387. + *
  3388. + * Copyright (C) 2010  Collabora, Ltd.
  3389. + * Copyright (C) 2003, 2005  Red Hat, Inc.
  3390. + *
  3391. + * Licensed under the Academic Free License version 2.1
  3392. + *
  3393. + * This program is free software; you can redistribute it and/or modify
  3394. + * it under the terms of the GNU General Public License as published by
  3395. + * the Free Software Foundation; either version 2 of the License, or
  3396. + * (at your option) any later version.
  3397. + *
  3398. + * This program is distributed in the hope that it will be useful,
  3399. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3400. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  3401. + * GNU General Public License for more details.
  3402. + *
  3403. + * You should have received a copy of the GNU General Public License
  3404. + * along with this program; if not, write to the Free Software
  3405. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  3406. + *
  3407. + */
  3408. +
  3409. +#include "matchrule.h"
  3410. +
  3411. +#include <linux/rbtree.h>
  3412. +
  3413. +#include "dbus-protocol.h"
  3414. +#include "message.h"
  3415. +
  3416. +struct BusMatchRule
  3417. +{
  3418. +  int refcount;       /**< reference count */
  3419. +
  3420. +  struct dbus_sock *matches_go_to; /**< Owner of the rule */
  3421. +
  3422. +  unsigned int flags; /**< BusMatchFlags */
  3423. +
  3424. +  int   message_type;
  3425. +  char *interface;
  3426. +  char *member;
  3427. +  char *sender;
  3428. +  char *destination;
  3429. +  char *path;
  3430. +
  3431. +  unsigned int *arg_lens;
  3432. +  char **args;
  3433. +  int args_len;
  3434. +
  3435. +  /* BusMatchRule is attached to RulePool, either in a simple double-linked
  3436. +   * list if the rule does not have any interface, or in a red-black tree
  3437. +   * sorted by interface. If several rules can have the same interface, the
  3438. +   * first one is attached with struct rb_node and the next ones are in the
  3439. +   * list */
  3440. +
  3441. +  struct rb_node node;
  3442. +  /* Doubly-linked non-circular list. If the rule has an interface, it is in
  3443. +   * the rb tree and the single head is right here. Otherwise, the single head
  3444. +   * is in RulePool->rules_without_iface. With this datastructure, we don't
  3445. +   * need any allocation to insert or remove the rule. */
  3446. +  struct hlist_head first;
  3447. +  struct hlist_node list;
  3448. +};
  3449. +
  3450. +#define BUS_MATCH_ARG_IS_PATH  0x8000000u
  3451. +
  3452. +#define DBUS_STRING_MAX_LENGTH 1024
  3453. +
  3454. +/** Max length of a match rule string; to keep people from hosing the
  3455. + * daemon with some huge rule
  3456. + */
  3457. +#define DBUS_MAXIMUM_MATCH_RULE_LENGTH 1024
  3458. +
  3459. +BusMatchRule*
  3460. +bus_match_rule_new (struct dbus_sock *matches_go_to)
  3461. +{
  3462. +  BusMatchRule *rule;
  3463. +
  3464. +  rule = kzalloc (sizeof (BusMatchRule), GFP_KERNEL);
  3465. +  if (rule == NULL)
  3466. +    return NULL;
  3467. +
  3468. +  rule->refcount = 1;
  3469. +  rule->matches_go_to = matches_go_to;
  3470. +
  3471. +  WARN_ON (!rule->matches_go_to);
  3472. +  
  3473. +  return rule;
  3474. +}
  3475. +
  3476. +BusMatchRule *
  3477. +bus_match_rule_ref (BusMatchRule *rule)
  3478. +{
  3479. +  WARN_ON (rule->refcount <= 0);
  3480. +
  3481. +  rule->refcount += 1;
  3482. +
  3483. +  return rule;
  3484. +}
  3485. +
  3486. +void
  3487. +bus_match_rule_unref (BusMatchRule *rule)
  3488. +{
  3489. +  WARN_ON (rule->refcount <= 0);
  3490. +
  3491. +  rule->refcount -= 1;
  3492. +  if (rule->refcount == 0)
  3493. +    {
  3494. +      if (rule->interface)
  3495. +        kfree (rule->interface);
  3496. +      if (rule->member)
  3497. +        kfree (rule->member);
  3498. +      if (rule->sender)
  3499. +        kfree (rule->sender);
  3500. +      if (rule->destination)
  3501. +        kfree (rule->destination);
  3502. +      if (rule->path)
  3503. +        kfree (rule->path);
  3504. +      if (rule->arg_lens)
  3505. +        kfree (rule->arg_lens);
  3506. +
  3507. +      /* can't use dbus_free_string_array() since there
  3508. +       * are embedded NULL
  3509. +       */
  3510. +      if (rule->args)
  3511. +        {
  3512. +          int i;
  3513. +
  3514. +          i = 0;
  3515. +          while (i < rule->args_len)
  3516. +            {
  3517. +              if (rule->args[i])
  3518. +                kfree (rule->args[i]);
  3519. +              ++i;
  3520. +            }
  3521. +
  3522. +          kfree (rule->args);
  3523. +        }
  3524. +      
  3525. +      kfree (rule);
  3526. +    }
  3527. +}
  3528. +
  3529. +/* Note this function does not do escaping, so it's only
  3530. + * good for debug spew at the moment
  3531. + */
  3532. +static char*
  3533. +match_rule_to_string (BusMatchRule *rule)
  3534. +{
  3535. +  char *str;
  3536. +  char *cur;
  3537. +  
  3538. +  cur = str = kmalloc (DBUS_STRING_MAX_LENGTH, GFP_KERNEL);
  3539. +  if (!str)
  3540. +    {
  3541. +      return NULL;
  3542. +    }
  3543. +  
  3544. +  if (rule->flags & BUS_MATCH_MESSAGE_TYPE)
  3545. +    {
  3546. +      /* FIXME make type readable */
  3547. +      cur += snprintf(cur, str - cur + DBUS_STRING_MAX_LENGTH,
  3548. +          "type='%d'", rule->message_type);
  3549. +    }
  3550. +
  3551. +  if (rule->flags & BUS_MATCH_INTERFACE)
  3552. +    {
  3553. +      if (cur != str)
  3554. +        {
  3555. +          cur += snprintf(cur, str - cur + DBUS_STRING_MAX_LENGTH,
  3556. +              ",");
  3557. +        }
  3558. +      
  3559. +      cur += snprintf(cur, str - cur + DBUS_STRING_MAX_LENGTH,
  3560. +          "interface='%s'", rule->interface);
  3561. +    }
  3562. +
  3563. +  if (rule->flags & BUS_MATCH_MEMBER)
  3564. +    {
  3565. +      if (cur != str)
  3566. +        {
  3567. +          cur += snprintf(cur, str - cur + DBUS_STRING_MAX_LENGTH,
  3568. +              ",");
  3569. +        }
  3570. +      
  3571. +      cur += snprintf(cur, str - cur + DBUS_STRING_MAX_LENGTH,
  3572. +          "member='%s'", rule->member);
  3573. +    }
  3574. +
  3575. +  if (rule->flags & BUS_MATCH_PATH)
  3576. +    {
  3577. +      if (cur != str)
  3578. +        {
  3579. +          cur += snprintf(cur, str - cur + DBUS_STRING_MAX_LENGTH,
  3580. +              ",");
  3581. +        }
  3582. +      
  3583. +      cur += snprintf(cur, str - cur + DBUS_STRING_MAX_LENGTH,
  3584. +          "path='%s'", rule->path);
  3585. +    }
  3586. +
  3587. +  if (rule->flags & BUS_MATCH_SENDER)
  3588. +    {
  3589. +      if (cur != str)
  3590. +        {
  3591. +          cur += snprintf(cur, str - cur + DBUS_STRING_MAX_LENGTH,
  3592. +              ",");
  3593. +        }
  3594. +      
  3595. +      cur += snprintf(cur, str - cur + DBUS_STRING_MAX_LENGTH,
  3596. +          "sender='%s'", rule->sender);
  3597. +    }
  3598. +
  3599. +  if (rule->flags & BUS_MATCH_DESTINATION)
  3600. +    {
  3601. +      if (cur != str)
  3602. +        {
  3603. +          cur += snprintf(cur, str - cur + DBUS_STRING_MAX_LENGTH,
  3604. +              ",");
  3605. +        }
  3606. +      
  3607. +      cur += snprintf(cur, str - cur + DBUS_STRING_MAX_LENGTH,
  3608. +          "destination='%s'", rule->destination);
  3609. +    }
  3610. +
  3611. +  if (rule->flags & BUS_MATCH_ARGS)
  3612. +    {
  3613. +      int i;
  3614. +      
  3615. +      WARN_ON (!rule->args);
  3616. +
  3617. +      i = 0;
  3618. +      while (i < rule->args_len)
  3619. +        {
  3620. +          if (rule->args[i] != NULL)
  3621. +            {
  3622. +              int is_path;
  3623. +
  3624. +              if (cur != str)
  3625. +                {
  3626. +                  cur += snprintf(cur, str - cur + DBUS_STRING_MAX_LENGTH,
  3627. +                      ",");
  3628. +                }
  3629. +
  3630. +              is_path = (rule->arg_lens[i] & BUS_MATCH_ARG_IS_PATH) != 0;
  3631. +              
  3632. +              cur += snprintf(cur, str - cur + DBUS_STRING_MAX_LENGTH,
  3633. +                  "arg%d%s='%s'", i, is_path ? "path" : "",
  3634. +                  rule->args[i]);
  3635. +            }
  3636. +          
  3637. +          ++i;
  3638. +        }
  3639. +    }
  3640. +  
  3641. +  return str;
  3642. +}
  3643. +
  3644. +int
  3645. +bus_match_rule_set_message_type (BusMatchRule *rule,
  3646. +                                 int           type)
  3647. +{
  3648. +  rule->flags |= BUS_MATCH_MESSAGE_TYPE;
  3649. +
  3650. +  rule->message_type = type;
  3651. +
  3652. +  return 1;
  3653. +}
  3654. +
  3655. +int
  3656. +bus_match_rule_set_interface (BusMatchRule *rule,
  3657. +                              const char   *interface)
  3658. +{
  3659. +  char *new;
  3660. +
  3661. +  WARN_ON (!interface);
  3662. +
  3663. +  new = kstrdup (interface, GFP_KERNEL);
  3664. +  if (new == NULL)
  3665. +    return 0;
  3666. +
  3667. +  rule->flags |= BUS_MATCH_INTERFACE;
  3668. +  kfree (rule->interface);
  3669. +  rule->interface = new;
  3670. +
  3671. +  return 1;
  3672. +}
  3673. +
  3674. +int
  3675. +bus_match_rule_set_member (BusMatchRule *rule,
  3676. +                           const char   *member)
  3677. +{
  3678. +  char *new;
  3679. +
  3680. +  WARN_ON(!member);
  3681. +
  3682. +  new = kstrdup (member, GFP_KERNEL);
  3683. +  if (new == NULL)
  3684. +    return 0;
  3685. +
  3686. +  rule->flags |= BUS_MATCH_MEMBER;
  3687. +  kfree (rule->member);
  3688. +  rule->member = new;
  3689. +
  3690. +  return 1;
  3691. +}
  3692. +
  3693. +int
  3694. +bus_match_rule_set_sender (BusMatchRule *rule,
  3695. +                           const char   *sender)
  3696. +{
  3697. +  char *new;
  3698. +
  3699. +  WARN_ON (!sender);
  3700. +
  3701. +  new = kstrdup (sender, GFP_KERNEL);
  3702. +  if (new == NULL)
  3703. +    return 0;
  3704. +
  3705. +  rule->flags |= BUS_MATCH_SENDER;
  3706. +  kfree (rule->sender);
  3707. +  rule->sender = new;
  3708. +
  3709. +  return 1;
  3710. +}
  3711. +
  3712. +int
  3713. +bus_match_rule_set_destination (BusMatchRule *rule,
  3714. +                                const char   *destination)
  3715. +{
  3716. +  char *new;
  3717. +
  3718. +  WARN_ON (!destination);
  3719. +
  3720. +  new = kstrdup (destination, GFP_KERNEL);
  3721. +  if (new == NULL)
  3722. +    return 0;
  3723. +
  3724. +  rule->flags |= BUS_MATCH_DESTINATION;
  3725. +  kfree (rule->destination);
  3726. +  rule->destination = new;
  3727. +
  3728. +  return 1;
  3729. +}
  3730. +
  3731. +int
  3732. +bus_match_rule_set_path (BusMatchRule *rule,
  3733. +                         const char   *path)
  3734. +{
  3735. +  char *new;
  3736. +
  3737. +  WARN_ON (!path);
  3738. +
  3739. +  new = kstrdup (path, GFP_KERNEL);
  3740. +  if (new == NULL)
  3741. +    return 0;
  3742. +
  3743. +  rule->flags |= BUS_MATCH_PATH;
  3744. +  kfree (rule->path);
  3745. +  rule->path = new;
  3746. +
  3747. +  return 1;
  3748. +}
  3749. +
  3750. +int
  3751. +bus_match_rule_set_arg (BusMatchRule     *rule,
  3752. +                        int                arg,
  3753. +                        const char *value,
  3754. +                        int       is_path)
  3755. +{
  3756. +  int length;
  3757. +  char *new;
  3758. +
  3759. +  /* args_len is the number of args not including null termination
  3760. +   * in the char**
  3761. +   */
  3762. +  if (arg >= rule->args_len)
  3763. +    {
  3764. +      unsigned int *new_arg_lens;
  3765. +      char **new_args;
  3766. +      int new_args_len;
  3767. +      int i;
  3768. +
  3769. +      new_args_len = arg + 1;
  3770. +
  3771. +      /* add another + 1 here for null termination */
  3772. +      new_args = krealloc (rule->args,
  3773. +          sizeof (char *) * (new_args_len + 1), GFP_KERNEL);
  3774. +      if (new_args == NULL)
  3775. +        return 0;
  3776. +
  3777. +      /* NULL the new slots */
  3778. +      i = rule->args_len;
  3779. +      while (i <= new_args_len) /* <= for null termination */
  3780. +        {
  3781. +          new_args[i] = NULL;
  3782. +          ++i;
  3783. +        }
  3784. +      
  3785. +      rule->args = new_args;
  3786. +
  3787. +      /* and now add to the lengths */
  3788. +      new_arg_lens = krealloc (rule->arg_lens,
  3789. +          sizeof (int) * (new_args_len + 1), GFP_KERNEL);
  3790. +
  3791. +      if (new_arg_lens == NULL)
  3792. +        return 0;
  3793. +
  3794. +      /* zero the new slots */
  3795. +      i = rule->args_len;
  3796. +      while (i <= new_args_len) /* <= for null termination */
  3797. +        {
  3798. +          new_arg_lens[i] = 0;
  3799. +          ++i;
  3800. +        }
  3801. +
  3802. +      rule->arg_lens = new_arg_lens;
  3803. +      rule->args_len = new_args_len;
  3804. +    }
  3805. +
  3806. +  length = strlen (value);
  3807. +  if (!(new = kstrdup (value, GFP_KERNEL)))
  3808. +    return 0;
  3809. +
  3810. +  rule->flags |= BUS_MATCH_ARGS;
  3811. +
  3812. +  kfree (rule->args[arg]);
  3813. +  rule->arg_lens[arg] = length;
  3814. +  rule->args[arg] = new;
  3815. +
  3816. +  if (is_path)
  3817. +    rule->arg_lens[arg] |= BUS_MATCH_ARG_IS_PATH;
  3818. +
  3819. +  return 1;
  3820. +}
  3821. +
  3822. +#define ISWHITE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || ((c) == '\r'))
  3823. +
  3824. +static int
  3825. +find_key (const char *str,
  3826. +          int               start,
  3827. +          char             *key,
  3828. +          int              *value_pos)
  3829. +{
  3830. +  const char *p;
  3831. +  const char *s;
  3832. +  const char *key_start;
  3833. +  const char *key_end;
  3834. +
  3835. +  s = str;
  3836. +
  3837. +  p = s + start;
  3838. +
  3839. +  while (*p && ISWHITE (*p))
  3840. +    ++p;
  3841. +
  3842. +  key_start = p;
  3843. +
  3844. +  while (*p && *p != '=' && !ISWHITE (*p))
  3845. +    ++p;
  3846. +
  3847. +  key_end = p;
  3848. +
  3849. +  while (*p && ISWHITE (*p))
  3850. +    ++p;
  3851. +  
  3852. +  if (key_start == key_end)
  3853. +    {
  3854. +      /* Empty match rules or trailing whitespace are OK */
  3855. +      *value_pos = p - s;
  3856. +      return 1;
  3857. +    }
  3858. +
  3859. +  if (*p != '=')
  3860. +    {
  3861. +      pr_warning("Match rule has a key with no subsequent '=' character");
  3862. +      return 0;
  3863. +    }
  3864. +  ++p;
  3865. +  
  3866. +  strncat (key, key_start, key_end - key_start);
  3867. +
  3868. +  *value_pos = p - s;
  3869. +  
  3870. +  return 1;
  3871. +}
  3872. +
  3873. +static int
  3874. +find_value (const char       *str,
  3875. +            int               start,
  3876. +            const char       *key,
  3877. +            char             *value,
  3878. +            int              *value_end)
  3879. +{
  3880. +  const char *p;
  3881. +  const char *s;
  3882. +  char quote_char;
  3883. +  int orig_len;
  3884. +
  3885. +  orig_len = strlen (value);
  3886. +  
  3887. +  s = str;
  3888. +
  3889. +  p = s + start;
  3890. +
  3891. +  quote_char = '\0';
  3892. +
  3893. +  while (*p)
  3894. +    {
  3895. +      if (quote_char == '\0')
  3896. +        {
  3897. +          switch (*p)
  3898. +            {
  3899. +            case '\0':
  3900. +              goto done;
  3901. +
  3902. +            case '\'':
  3903. +              quote_char = '\'';
  3904. +              goto next;
  3905. +              
  3906. +            case ',':
  3907. +              ++p;
  3908. +              goto done;
  3909. +
  3910. +            case '\\':
  3911. +              quote_char = '\\';
  3912. +              goto next;
  3913. +              
  3914. +            default:
  3915. +              strncat(value, p, 1);
  3916. +            }
  3917. +        }
  3918. +      else if (quote_char == '\\')
  3919. +        {
  3920. +          /* \ only counts as an escape if escaping a quote mark */
  3921. +          if (*p != '\'')
  3922. +            {
  3923. +              strncat(value, "\\", 1);
  3924. +            }
  3925. +
  3926. +          strncat(value, p, 1);
  3927. +          
  3928. +          quote_char = '\0';
  3929. +        }
  3930. +      else
  3931. +        {
  3932. +          if (*p == '\'')
  3933. +            {
  3934. +              quote_char = '\0';
  3935. +            }
  3936. +          else
  3937. +            {
  3938. +              strncat(value, p, 1);
  3939. +            }
  3940. +        }
  3941. +
  3942. +    next:
  3943. +      ++p;
  3944. +    }
  3945. +
  3946. + done:
  3947. +
  3948. +  if (quote_char == '\\')
  3949. +    {
  3950. +      strncat(value, "\\", 1);
  3951. +    }
  3952. +  else if (quote_char == '\'')
  3953. +    {
  3954. +      pr_warning ("Unbalanced quotation marks in match rule");
  3955. +      return 0;
  3956. +    }
  3957. +
  3958. +  /* Zero-length values are allowed */
  3959. +  
  3960. +  *value_end = p - s;
  3961. +  
  3962. +  return 1;
  3963. +}
  3964. +
  3965. +/* duplicates aren't allowed so the real legitimate max is only 6 or
  3966. + * so. Leaving extra so we don't have to bother to update it.
  3967. + * FIXME this is sort of busted now with arg matching, but we let
  3968. + * you match on up to 10 args for now
  3969. + */
  3970. +#define MAX_RULE_TOKENS 16
  3971. +
  3972. +/* this is slightly too high level to be termed a "token"
  3973. + * but let's not be pedantic.
  3974. + */
  3975. +typedef struct
  3976. +{
  3977. +  char *key;
  3978. +  char *value;
  3979. +} RuleToken;
  3980. +
  3981. +static int
  3982. +tokenize_rule (const char *rule_text,
  3983. +               RuleToken         tokens[MAX_RULE_TOKENS])
  3984. +{
  3985. +  int i;
  3986. +  int pos;
  3987. +  int retval;
  3988. +
  3989. +  retval = 0;
  3990. +  
  3991. +  i = 0;
  3992. +  pos = 0;
  3993. +  while (i < MAX_RULE_TOKENS &&
  3994. +         pos < strlen (rule_text))
  3995. +    {
  3996. +      char *key;
  3997. +      char *value;
  3998. +
  3999. +      key = kzalloc (DBUS_STRING_MAX_LENGTH, GFP_KERNEL);
  4000. +      if (!key)
  4001. +        {
  4002. +          printk("Out of memory");
  4003. +          BUG();
  4004. +          return 0;
  4005. +        }
  4006. +
  4007. +      value = kzalloc (DBUS_STRING_MAX_LENGTH, GFP_KERNEL);
  4008. +      if (!value)
  4009. +        {
  4010. +          kfree(key);
  4011. +          printk("Out of memory");
  4012. +          BUG();
  4013. +          return 0;
  4014. +        }
  4015. +
  4016. +      if (!find_key (rule_text, pos, key, &pos))
  4017. +        goto out;
  4018. +
  4019. +      if (strlen (key) == 0)
  4020. +        goto next;
  4021. +      
  4022. +      tokens[i].key = key;
  4023. +
  4024. +      if (!find_value (rule_text, pos, tokens[i].key, value, &pos))
  4025. +        goto out;
  4026. +
  4027. +      tokens[i].value = value;
  4028. +
  4029. +    next:
  4030. +      ++i;
  4031. +    }
  4032. +
  4033. +  retval = 1;
  4034. +  
  4035. + out:
  4036. +  if (!retval)
  4037. +    {
  4038. +      i = 0;
  4039. +      while (tokens[i].key || tokens[i].value)
  4040. +        {
  4041. +          kfree (tokens[i].key);
  4042. +          kfree (tokens[i].value);
  4043. +          tokens[i].key = NULL;
  4044. +          tokens[i].value = NULL;
  4045. +          ++i;
  4046. +        }
  4047. +    }
  4048. +  
  4049. +  return retval;
  4050. +}
  4051. +
  4052. +#if 0
  4053. +static int
  4054. +bus_match_rule_parse_arg_match (BusMatchRule     *rule,
  4055. +                                const char       *key,
  4056. +                                const char       *value)
  4057. +{
  4058. +  int is_path;
  4059. +  DBusString key_str;
  4060. +  unsigned long arg;
  4061. +  int length;
  4062. +  int end;
  4063. +
  4064. +  /* For now, arg0='foo' always implies that 'foo' is a
  4065. +   * DBUS_TYPE_STRING. Someday we could add an arg0type='int32' thing
  4066. +   * if we wanted, which would specify another type, in which case
  4067. +   * arg0='5' would have the 5 parsed as an int rather than string.
  4068. +   */
  4069. +  
  4070. +  /* First we need to parse arg0 = 0, arg27 = 27 */
  4071. +
  4072. +  _dbus_string_init_const (&key_str, key);
  4073. +  length = _dbus_string_get_length (&key_str);
  4074. +
  4075. +  if (_dbus_string_get_length (&key_str) < 4)
  4076. +    {
  4077. +      dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
  4078. +                      "Key '%s' in match rule starts with 'arg' but lacks an arg number. Should be 'arg0' or 'arg7' for example.\n", key);
  4079. +      goto failed;
  4080. +    }
  4081. +
  4082. +  if (!_dbus_string_parse_uint (&key_str, 3, &arg, &end))
  4083. +    {
  4084. +      dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
  4085. +                      "Key '%s' in match rule starts with 'arg' but could not parse arg number. Should be 'arg0' or 'arg7' for example.\n", key);
  4086. +      goto failed;
  4087. +    }
  4088. +
  4089. +  if (end != length &&
  4090. +      ((end + 4) != length ||
  4091. +       !_dbus_string_ends_with_c_str (&key_str, "path")))
  4092. +    {
  4093. +      dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
  4094. +                      "Key '%s' in match rule contains junk after argument number. Only 'path' is optionally valid ('arg0path' for example).\n", key);
  4095. +      goto failed;
  4096. +    }
  4097. +
  4098. +  is_path = end != length;
  4099. +
  4100. +  /* If we didn't check this we could allocate a huge amount of RAM */
  4101. +  if (arg > DBUS_MAXIMUM_MATCH_RULE_ARG_NUMBER)
  4102. +    {
  4103. +      printk("Key '%s' in match rule has arg number %lu but the maximum is %d.\n", key, (unsigned long) arg, DBUS_MAXIMUM_MATCH_RULE_ARG_NUMBER);
  4104. +      dump_stack();
  4105. +      return 0;
  4106. +    }
  4107. +  
  4108. +  if ((rule->flags & BUS_MATCH_ARGS) &&
  4109. +      rule->args_len > (int) arg &&
  4110. +      rule->args[arg] != NULL)
  4111. +    {
  4112. +      printk("Argument %d matched more than once in match rule\n", key);
  4113. +      dump_stack();
  4114. +      return 0;
  4115. +    }
  4116. +  
  4117. +  if (!bus_match_rule_set_arg (rule, arg, value, is_path))
  4118. +    {
  4119. +      printk("Out of memory");
  4120. +      dump_stack();
  4121. +      return 0;
  4122. +    }
  4123. +
  4124. +  return 1;
  4125. +}
  4126. +#endif
  4127. +
  4128. +/*
  4129. + * The format is comma-separated with strings quoted with single quotes
  4130. + * as for the shell (to escape a literal single quote, use '\'').
  4131. + *
  4132. + * type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='Foo',
  4133. + * path='/bar/foo',destination=':452345.34'
  4134. + *
  4135. + */
  4136. +BusMatchRule*
  4137. +bus_match_rule_parse (struct dbus_sock   *matches_go_to,
  4138. +                      const char         *rule_text)
  4139. +{
  4140. +  BusMatchRule *rule;
  4141. +  RuleToken tokens[MAX_RULE_TOKENS+1]; /* NULL termination + 1 */
  4142. +  int i;
  4143. +  
  4144. +  if (strlen (rule_text) > DBUS_MAXIMUM_MATCH_RULE_LENGTH)
  4145. +    {
  4146. +      pr_warning ("Match rule text is %d bytes, maximum is %d",
  4147. +                      strlen (rule_text),
  4148. +                      DBUS_MAXIMUM_MATCH_RULE_LENGTH);
  4149. +      return NULL;
  4150. +    }
  4151. +  
  4152. +  memset (tokens, '\0', sizeof (tokens));
  4153. +  
  4154. +  rule = bus_match_rule_new (matches_go_to);
  4155. +  if (rule == NULL)
  4156. +    {
  4157. +      printk("Out of memory");
  4158. +      BUG();
  4159. +      goto failed;
  4160. +    }
  4161. +  
  4162. +  if (!tokenize_rule (rule_text, tokens))
  4163. +    goto failed;
  4164. +  
  4165. +  i = 0;
  4166. +  while (tokens[i].key != NULL)
  4167. +    {
  4168. +#if 0
  4169. +      char *tmp_str;
  4170. +      int len;
  4171. +#endif
  4172. +      const char *key = tokens[i].key;
  4173. +      const char *value = tokens[i].value;
  4174. +      
  4175. +#if 0
  4176. +      tmp_str = value;
  4177. +      len = strlen (tmp_str);
  4178. +#endif
  4179. +
  4180. +      if (strcmp (key, "type") == 0)
  4181. +        {
  4182. +          int t;
  4183. +
  4184. +          if (rule->flags & BUS_MATCH_MESSAGE_TYPE)
  4185. +            {
  4186. +              pr_warning("Key %s specified twice in match rule\n", key);
  4187. +              goto failed;
  4188. +            }
  4189. +          
  4190. +          t = dbus_message_type_from_string (value);
  4191. +          
  4192. +          if (t == DBUS_MESSAGE_TYPE_INVALID)
  4193. +            {
  4194. +              pr_warning("Invalid message type (%s) in match rule\n", value);
  4195. +              goto failed;
  4196. +            }
  4197. +
  4198. +          if (!bus_match_rule_set_message_type (rule, t))
  4199. +            {
  4200. +              printk("Out of memeory");
  4201. +              BUG();
  4202. +              goto failed;
  4203. +            }
  4204. +        }
  4205. +      else if (strcmp (key, "sender") == 0)
  4206. +        {
  4207. +          if (rule->flags & BUS_MATCH_SENDER)
  4208. +            {
  4209. +              pr_warning("Key %s specified twice in match rule\n", key);
  4210. +              goto failed;
  4211. +            }
  4212. +
  4213. +#if 0
  4214. +          if (!_dbus_validate_bus_name (tmp_str, 0, len))
  4215. +            {
  4216. +              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
  4217. +                              "Sender name '%s' is invalid\n", value);
  4218. +              goto failed;
  4219. +            }
  4220. +#endif
  4221. +
  4222. +          if (!bus_match_rule_set_sender (rule, value))
  4223. +            {
  4224. +              printk("Out of memeory");
  4225. +              BUG();
  4226. +              goto failed;
  4227. +            }
  4228. +        }
  4229. +      else if (strcmp (key, "interface") == 0)
  4230. +        {
  4231. +          if (rule->flags & BUS_MATCH_INTERFACE)
  4232. +            {
  4233. +              pr_warning("Key %s specified twice in match rule\n", key);
  4234. +              goto failed;
  4235. +            }
  4236. +
  4237. +#if 0
  4238. +          if (!_dbus_validate_interface (tmp_str, 0, len))
  4239. +            {
  4240. +              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
  4241. +                              "Interface name '%s' is invalid\n", value);
  4242. +              goto failed;
  4243. +            }
  4244. +#endif
  4245. +
  4246. +          if (!bus_match_rule_set_interface (rule, value))
  4247. +            {
  4248. +              printk("Out of memeory");
  4249. +              BUG();
  4250. +              goto failed;
  4251. +            }
  4252. +        }
  4253. +      else if (strcmp (key, "member") == 0)
  4254. +        {
  4255. +          if (rule->flags & BUS_MATCH_MEMBER)
  4256. +            {
  4257. +              pr_warning("Key %s specified twice in match rule\n", key);
  4258. +              goto failed;
  4259. +            }
  4260. +
  4261. +#if 0
  4262. +          if (!_dbus_validate_member (tmp_str, 0, len))
  4263. +            {
  4264. +              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
  4265. +                              "Member name '%s' is invalid\n", value);
  4266. +              goto failed;
  4267. +            }
  4268. +#endif
  4269. +
  4270. +          if (!bus_match_rule_set_member (rule, value))
  4271. +            {
  4272. +              printk("Out of memeory");
  4273. +              BUG();
  4274. +              goto failed;
  4275. +            }
  4276. +        }
  4277. +      else if (strcmp (key, "path") == 0)
  4278. +        {
  4279. +          if (rule->flags & BUS_MATCH_PATH)
  4280. +            {
  4281. +              pr_warning("Key %s specified twice in match rule\n", key);
  4282. +              goto failed;
  4283. +            }
  4284. +
  4285. +#if 0
  4286. +          if (!_dbus_validate_path (tmp_str, 0, len))
  4287. +            {
  4288. +              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
  4289. +                              "Path '%s' is invalid\n", value);
  4290. +              goto failed;
  4291. +            }
  4292. +#endif
  4293. +
  4294. +          if (!bus_match_rule_set_path (rule, value))
  4295. +            {
  4296. +              printk("Out of memeory");
  4297. +              BUG();
  4298. +              goto failed;
  4299. +            }
  4300. +        }
  4301. +      else if (strcmp (key, "destination") == 0)
  4302. +        {
  4303. +          if (rule->flags & BUS_MATCH_DESTINATION)
  4304. +            {
  4305. +              pr_warning("Key %s specified twice in match rule\n", key);
  4306. +              goto failed;
  4307. +            }
  4308. +
  4309. +#if 0
  4310. +          if (!_dbus_validate_bus_name (tmp_str, 0, len))
  4311. +            {
  4312. +              dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
  4313. +                              "Destination name '%s' is invalid\n", value);
  4314. +              goto failed;
  4315. +            }
  4316. +#endif
  4317. +
  4318. +          if (!bus_match_rule_set_destination (rule, value))
  4319. +            {
  4320. +              printk("Out of memeory");
  4321. +              BUG();
  4322. +              goto failed;
  4323. +            }
  4324. +        }
  4325. +      else if (strncmp (key, "arg", 3) == 0)
  4326. +        {
  4327. +#if 0
  4328. +          if (!bus_match_rule_parse_arg_match (rule, key, &tmp_str, error))
  4329. +            goto failed;
  4330. +#endif
  4331. +        }
  4332. +      else
  4333. +        {
  4334. +          pr_warning("Unknown key \"%s\" in match rule\n",
  4335. +                          key);
  4336. +          goto failed;
  4337. +        }
  4338. +
  4339. +      ++i;
  4340. +    }
  4341. +  
  4342. +
  4343. +  goto out;
  4344. +  
  4345. + failed:
  4346. +  if (rule)
  4347. +    {
  4348. +      bus_match_rule_unref (rule);
  4349. +      rule = NULL;
  4350. +    }
  4351. +
  4352. + out:
  4353. +  
  4354. +  i = 0;
  4355. +  while (tokens[i].key || tokens[i].value)
  4356. +    {
  4357. +      WARN_ON (i >= MAX_RULE_TOKENS);
  4358. +      kfree (tokens[i].key);
  4359. +      kfree (tokens[i].value);
  4360. +      ++i;
  4361. +    }
  4362. +  
  4363. +  return rule;
  4364. +}
  4365. +
  4366. +typedef struct RulePool RulePool;
  4367. +struct RulePool
  4368. +{
  4369. +  /* Maps non-NULL interface names to a list of BusMatchRule */
  4370. +  struct rb_root rules_by_iface;
  4371. +
  4372. +  /* List of BusMatchRules which don't specify an interface */
  4373. +  struct hlist_head rules_without_iface;
  4374. +};
  4375. +
  4376. +struct BusMatchmaker
  4377. +{
  4378. +  int refcount;
  4379. +
  4380. +  /* Pools of rules, grouped by the type of message they match. 0
  4381. +   * (DBUS_MESSAGE_TYPE_INVALID) represents rules that do not specify a message
  4382. +   * type.
  4383. +   */
  4384. +  RulePool rules_by_type[DBUS_NUM_MESSAGE_TYPES];
  4385. +};
  4386. +
  4387. +/* return the match rule containing the hlist_head. It may not be the first
  4388. + * match rule in the list. */
  4389. +struct BusMatchRule *match_rule_search(struct rb_root *root, const char *interface)
  4390. +{
  4391. +      struct rb_node *node = root->rb_node;
  4392. +
  4393. +      while (node) {
  4394. +              struct BusMatchRule *data = container_of(node,
  4395. +                  struct BusMatchRule, node);
  4396. +              int result;
  4397. +
  4398. +              result = strcmp(interface, data->interface);
  4399. +
  4400. +              if (result < 0)
  4401. +                      node = node->rb_left;
  4402. +              else if (result > 0)
  4403. +                      node = node->rb_right;
  4404. +              else
  4405. +                      return data;
  4406. +      }
  4407. +      return NULL;
  4408. +}
  4409. +
  4410. +void match_rule_insert(struct rb_root *root, struct BusMatchRule *data)
  4411. +{
  4412. +      struct rb_node **new = &(root->rb_node), *parent = NULL;
  4413. +
  4414. +      /* Figure out where to put new node */
  4415. +      while (*new) {
  4416. +              struct BusMatchRule *this = container_of(*new,
  4417. +                  struct BusMatchRule, node);
  4418. +              int result = strcmp(data->interface, this->interface);
  4419. +
  4420. +              parent = *new;
  4421. +              if (result < 0)
  4422. +                      new = &((*new)->rb_left);
  4423. +              else if (result > 0)
  4424. +                      new = &((*new)->rb_right);
  4425. +              else {
  4426. +                      /* the head is not used */
  4427. +                      INIT_HLIST_HEAD(&data->first);
  4428. +                      /* Add it at the beginning of the list */
  4429. +                      hlist_add_head(&data->list, &this->first);
  4430. +                      return;
  4431. +              }
  4432. +      }
  4433. +
  4434. +      /* this rule is single in its list */
  4435. +      INIT_HLIST_HEAD(&data->first);
  4436. +      hlist_add_head(&data->list, &data->first);
  4437. +
  4438. +      /* Add new node and rebalance tree. */
  4439. +      rb_link_node(&data->node, parent, new);
  4440. +      rb_insert_color(&data->node, root);
  4441. +}
  4442. +
  4443. +BusMatchmaker*
  4444. +bus_matchmaker_new (void)
  4445. +{
  4446. +  BusMatchmaker *matchmaker;
  4447. +  int i;
  4448. +
  4449. +  matchmaker = kzalloc (sizeof (BusMatchmaker), GFP_KERNEL);
  4450. +  if (matchmaker == NULL)
  4451. +    return NULL;
  4452. +
  4453. +  matchmaker->refcount = 1;
  4454. +
  4455. +  for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++)
  4456. +    {
  4457. +      RulePool *p = matchmaker->rules_by_type + i;
  4458. +
  4459. +      p->rules_by_iface = RB_ROOT;
  4460. +    }
  4461. +
  4462. +  return matchmaker;
  4463. +}
  4464. +
  4465. +BusMatchmaker *
  4466. +bus_matchmaker_ref (BusMatchmaker *matchmaker)
  4467. +{
  4468. +  WARN_ON (matchmaker->refcount <= 0);
  4469. +
  4470. +  matchmaker->refcount += 1;
  4471. +
  4472. +  return matchmaker;
  4473. +}
  4474. +
  4475. +void
  4476. +bus_matchmaker_unref (BusMatchmaker *matchmaker)
  4477. +{
  4478. +  WARN_ON (matchmaker->refcount <= 0);
  4479. +
  4480. +  matchmaker->refcount -= 1;
  4481. +  if (matchmaker->refcount == 0)
  4482. +    {
  4483. +      // FIXME: LEAK!!
  4484. +      kfree (matchmaker);
  4485. +    }
  4486. +}
  4487. +
  4488. +/* The rule can't be modified after it's added. */
  4489. +int
  4490. +bus_matchmaker_add_rule (BusMatchmaker   *matchmaker,
  4491. +                         BusMatchRule    *rule)
  4492. +{
  4493. +  RulePool *pool;
  4494. +
  4495. +  WARN_ON (rule->message_type < 0);
  4496. +  WARN_ON (rule->message_type >= DBUS_NUM_MESSAGE_TYPES);
  4497. +
  4498. +  pool = matchmaker->rules_by_type + rule->message_type;
  4499. +
  4500. +  if (rule->interface) {
  4501. +    match_rule_insert (&pool->rules_by_iface, rule);
  4502. +  } else {
  4503. +    hlist_add_head(&rule->list, &pool->rules_without_iface);
  4504. +  }
  4505. +  
  4506. +  return 1;
  4507. +}
  4508. +
  4509. +static int
  4510. +match_rule_equal (BusMatchRule *a,
  4511. +                  BusMatchRule *b)
  4512. +{
  4513. +  if (a->flags != b->flags)
  4514. +    return 0;
  4515. +
  4516. +  if (a->matches_go_to != b->matches_go_to)
  4517. +    return 0;
  4518. +
  4519. +  if ((a->flags & BUS_MATCH_MESSAGE_TYPE) &&
  4520. +      a->message_type != b->message_type)
  4521. +    return 0;
  4522. +
  4523. +  if ((a->flags & BUS_MATCH_MEMBER) &&
  4524. +      strcmp (a->member, b->member) != 0)
  4525. +    return 0;
  4526. +
  4527. +  if ((a->flags & BUS_MATCH_PATH) &&
  4528. +      strcmp (a->path, b->path) != 0)
  4529. +    return 0;
  4530. +  
  4531. +  if ((a->flags & BUS_MATCH_INTERFACE) &&
  4532. +      strcmp (a->interface, b->interface) != 0)
  4533. +    return 0;
  4534. +
  4535. +  if ((a->flags & BUS_MATCH_SENDER) &&
  4536. +      strcmp (a->sender, b->sender) != 0)
  4537. +    return 0;
  4538. +
  4539. +  if ((a->flags & BUS_MATCH_DESTINATION) &&
  4540. +      strcmp (a->destination, b->destination) != 0)
  4541. +    return 0;
  4542. +
  4543. +  if (a->flags & BUS_MATCH_ARGS)
  4544. +    {
  4545. +      int i;
  4546. +      
  4547. +      if (a->args_len != b->args_len)
  4548. +        return 0;
  4549. +      
  4550. +      i = 0;
  4551. +      while (i < a->args_len)
  4552. +        {
  4553. +          int length;
  4554. +
  4555. +          if ((a->args[i] != NULL) != (b->args[i] != NULL))
  4556. +            return 0;
  4557. +
  4558. +          if (a->arg_lens[i] != b->arg_lens[i])
  4559. +            return 0;
  4560. +
  4561. +          length = a->arg_lens[i] & ~BUS_MATCH_ARG_IS_PATH;
  4562. +
  4563. +          if (a->args[i] != NULL)
  4564. +            {
  4565. +              WARN_ON (!b->args[i]);
  4566. +              if (memcmp (a->args[i], b->args[i], length) != 0)
  4567. +                return 0;
  4568. +            }
  4569. +          
  4570. +          ++i;
  4571. +        }
  4572. +    }
  4573. +  
  4574. +  return 1;
  4575. +}
  4576. +
  4577. +void
  4578. +bus_matchmaker_remove_rule (BusMatchmaker   *matchmaker,
  4579. +                            BusMatchRule    *rule)
  4580. +{
  4581. +  RulePool *pool;
  4582. +
  4583. +  WARN_ON (rule->message_type < 0);
  4584. +  WARN_ON (rule->message_type >= DBUS_NUM_MESSAGE_TYPES);
  4585. +
  4586. +  pool = matchmaker->rules_by_type + rule->message_type;
  4587. +
  4588. +  if (rule->interface) {
  4589. +    BusMatchRule *head = match_rule_search(&pool->rules_by_iface,
  4590. +        rule->interface);
  4591. +    hlist_del(&rule->list);
  4592. +    if (!hlist_empty(&head->first) && head == rule) {
  4593. +      BusMatchRule *next = hlist_entry(head->first.first,
  4594. +          BusMatchRule, list);
  4595. +      hlist_move_list(&head->first, &next->first);
  4596. +    }
  4597. +    //XXX what _if we need to remove the rb_node entry: rb_erase
  4598. +  } else {
  4599. +    hlist_del(&rule->list);
  4600. +  }
  4601. +  //bus_match_rule_unref (rule); // cf XXX
  4602. +}
  4603. +
  4604. +/* Remove a single rule which is equal to the given rule by value */
  4605. +void
  4606. +bus_matchmaker_remove_rule_by_value (BusMatchmaker   *matchmaker,
  4607. +                                     BusMatchRule    *rule)
  4608. +{
  4609. +  RulePool *pool;
  4610. +
  4611. +  WARN_ON (rule->message_type < 0);
  4612. +  WARN_ON (rule->message_type >= DBUS_NUM_MESSAGE_TYPES);
  4613. +
  4614. +  pool = matchmaker->rules_by_type + rule->message_type;
  4615. +
  4616. +  if (rule->interface) {
  4617. +    BusMatchRule *head = match_rule_search(&pool->rules_by_iface,
  4618. +        rule->interface);
  4619. +    hlist_del(&rule->list);
  4620. +    if (!hlist_empty(&head->first) && match_rule_equal(head, rule)) {
  4621. +      BusMatchRule *next = hlist_entry(head->first.first,
  4622. +          BusMatchRule, list);
  4623. +      hlist_move_list(&head->first, &next->first);
  4624. +    }
  4625. +  } else {
  4626. +    hlist_del(&rule->list);
  4627. +  }
  4628. +  //bus_match_rule_unref (rule); // cf XXX
  4629. +}
  4630. +
  4631. +static void
  4632. +rule_list_remove_by_connection (BusMatchmaker *matchmaker,
  4633. +                                struct hlist_head *rules,
  4634. +                                struct dbus_sock  *connection)
  4635. +{
  4636. +  struct hlist_node *cur, *next;
  4637. +  BusMatchRule *rule;
  4638. +
  4639. +  if (rules == NULL)
  4640. +    return;
  4641. +
  4642. +  hlist_for_each_entry_safe(rule, cur, next, rules, list)
  4643. +    {
  4644. +      char *s = match_rule_to_string (rule);
  4645. +
  4646. +      if (rule->matches_go_to == connection) {
  4647. +        pr_debug("Delete rule \"%s\" because it is the owner of the rule\n", s);
  4648. +        kfree(s);
  4649. +        bus_matchmaker_remove_rule(matchmaker, rule);
  4650. +      } else if (((rule->flags & BUS_MATCH_SENDER) && *rule->sender == ':') ||
  4651. +                 ((rule->flags & BUS_MATCH_DESTINATION) && *rule->destination == ':')) {
  4652. +        /* The rule matches to/from a base service, see if it's the
  4653. +         * one being disconnected, since we know this service name
  4654. +         * will never be recycled.
  4655. +         */
  4656. +        const char *name;
  4657. +
  4658. +        name = connection->uniq_name;
  4659. +        if (!name)
  4660. +          {
  4661. +            kfree(s);
  4662. +            continue;
  4663. +          }
  4664. +
  4665. +        if (((rule->flags & BUS_MATCH_SENDER) &&
  4666. +             strcmp (rule->sender, name) == 0) ||
  4667. +            ((rule->flags & BUS_MATCH_DESTINATION) &&
  4668. +             strcmp (rule->destination, name) == 0))
  4669. +          {
  4670. +            pr_debug("Delete rule \"%s\" because of sender or destination\n", s);
  4671. +            bus_matchmaker_remove_rule(matchmaker, rule);
  4672. +          }
  4673. +        kfree(s);
  4674. +      }
  4675. +
  4676. +    }
  4677. +}
  4678. +
  4679. +void
  4680. +bus_matchmaker_disconnected (BusMatchmaker   *matchmaker,
  4681. +                             struct dbus_sock  *connection)
  4682. +{
  4683. +  int i;
  4684. +
  4685. +  /* FIXME
  4686. +   *
  4687. +   * This scans all match rules on the bus. We could avoid that
  4688. +   * for the rules belonging to the connection, since we keep
  4689. +   * a list of those; but for the rules that just refer to
  4690. +   * the connection we'd need to do something more elaborate.
  4691. +   */
  4692. +
  4693. +  pr_debug ("Removing all rules for connection '%s'\n",
  4694. +      connection->uniq_name ? connection->uniq_name : "(null)");
  4695. +  for (i = 0; i < MAX_WELL_KNOWN_NAMES; i++)
  4696. +    if (connection->well_known_names[i])
  4697. +      pr_debug(" - including well known name '%s'\n",
  4698. +          connection->well_known_names[i]);
  4699. +
  4700. +  for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++)
  4701. +    {
  4702. +      RulePool *p = matchmaker->rules_by_type + i;
  4703. +      struct rb_node *node;
  4704. +
  4705. +      rule_list_remove_by_connection (matchmaker,
  4706. +          &p->rules_without_iface, connection);
  4707. +
  4708. +      for (node = rb_first(&p->rules_by_iface); node; node = rb_next(node)) {
  4709. +        pr_debug("interface=%s\n",
  4710. +            rb_entry(node, struct BusMatchRule, node)->interface);
  4711. +        rule_list_remove_by_connection (matchmaker,
  4712. +            &rb_entry(node, struct BusMatchRule, node)->first, connection);
  4713. +      }
  4714. +    }
  4715. +
  4716. +  pr_debug("bus_matchmaker_disconnected: Finished :-)\n");
  4717. +}
  4718. +
  4719. +static int
  4720. +connection_is_primary_owner (struct dbus_sock *connection,
  4721. +                             const char     *service_name)
  4722. +{
  4723. +#if 0
  4724. +  BusService *service;
  4725. +  DBusString str;
  4726. +  BusRegistry *registry;
  4727. +
  4728. +  _dbus_assert (connection != NULL);
  4729. +  
  4730. +  registry = bus_connection_get_registry (connection);
  4731. +
  4732. +  _dbus_string_init_const (&str, service_name);
  4733. +  service = bus_registry_lookup (registry, &str);
  4734. +
  4735. +  if (service == NULL)
  4736. +    return 0; /* Service doesn't exist so connection can't own it. */
  4737. +
  4738. +  return bus_service_get_primary_owners_connection (service) == connection;
  4739. +#endif
  4740. +  return 1;
  4741. +}
  4742. +
  4743. +static int
  4744. +match_rule_matches (BusMatchRule    *rule,
  4745. +                    struct dbus_sock  *sender,
  4746. +                    struct dbus_sock  *addressed_recipient,
  4747. +                    const struct DBusMessage     *message,
  4748. +                    BusMatchFlags    already_matched)
  4749. +{
  4750. +  int flags;
  4751. +
  4752. +  /* All features of the match rule are AND'd together,
  4753. +   * so 0 if any of them don't match.
  4754. +   */
  4755. +
  4756. +  /* sender/addressed_recipient of #NULL may mean bus driver,
  4757. +   * or for addressed_recipient may mean a message with no
  4758. +   * specific recipient (i.e. a signal)
  4759. +   */
  4760. +
  4761. +  /* Don't bother re-matching features we've already checked implicitly. */
  4762. +  flags = rule->flags & (~already_matched);
  4763. +
  4764. +  if (flags & BUS_MATCH_MESSAGE_TYPE)
  4765. +    {
  4766. +      WARN_ON (rule->message_type == DBUS_MESSAGE_TYPE_INVALID);
  4767. +
  4768. +      if (rule->message_type != message->type)
  4769. +        return 0;
  4770. +    }
  4771. +
  4772. +  if (flags & BUS_MATCH_INTERFACE)
  4773. +    {
  4774. +      const char *iface;
  4775. +
  4776. +      WARN_ON (!rule->interface);
  4777. +
  4778. +      iface = message->interface;
  4779. +      if (iface == NULL)
  4780. +        return 0;
  4781. +
  4782. +      if (strcmp (iface, rule->interface) != 0)
  4783. +        return 0;
  4784. +    }
  4785. +
  4786. +  if (flags & BUS_MATCH_MEMBER)
  4787. +    {
  4788. +      const char *member;
  4789. +
  4790. +      WARN_ON (!rule->member);
  4791. +
  4792. +      member = message->member;
  4793. +      if (member == NULL)
  4794. +        return 0;
  4795. +
  4796. +      if (strcmp (member, rule->member) != 0)
  4797. +        return 0;
  4798. +    }
  4799. +
  4800. +  if (flags & BUS_MATCH_SENDER)
  4801. +    {
  4802. +      WARN_ON (!rule->sender);
  4803. +
  4804. +      if (sender == NULL)
  4805. +        {
  4806. +          if (strcmp (rule->sender,
  4807. +                      "org.freedesktop.DBus") != 0)
  4808. +            return 0;
  4809. +        }
  4810. +      else
  4811. +        {
  4812. +          if (!connection_is_primary_owner (sender, rule->sender))
  4813. +            return 0;
  4814. +        }
  4815. +    }
  4816. +
  4817. +  if (flags & BUS_MATCH_DESTINATION)
  4818. +    {
  4819. +      const char *destination;
  4820. +
  4821. +      WARN_ON (!rule->destination);
  4822. +
  4823. +      destination = message->destination;
  4824. +      if (destination == NULL)
  4825. +        return 0;
  4826. +
  4827. +      if (addressed_recipient == NULL)
  4828. +        {          
  4829. +          if (strcmp (rule->destination,
  4830. +                      "org.freedesktop.DBus") != 0)
  4831. +            return 0;
  4832. +        }
  4833. +      else
  4834. +        {
  4835. +          if (!connection_is_primary_owner (addressed_recipient, rule->destination))
  4836. +            return 0;
  4837. +        }
  4838. +    }
  4839. +
  4840. +  if (flags & BUS_MATCH_PATH)
  4841. +    {
  4842. +      const char *path;
  4843. +
  4844. +      WARN_ON (!rule->path);
  4845. +
  4846. +      path = message->path;
  4847. +      if (path == NULL)
  4848. +        return 0;
  4849. +
  4850. +      if (strcmp (path, rule->path) != 0)
  4851. +        return 0;
  4852. +    }
  4853. +
  4854. +#if 0
  4855. +  if (flags & BUS_MATCH_ARGS)
  4856. +    {
  4857. +      int i;
  4858. +      DBusMessageIter iter;
  4859. +      
  4860. +      _dbus_assert (rule->args != NULL);
  4861. +
  4862. +      dbus_message_iter_init (message, &iter);
  4863. +      
  4864. +      i = 0;
  4865. +      while (i < rule->args_len)
  4866. +        {
  4867. +          int current_type;
  4868. +          const char *expected_arg;
  4869. +          int expected_length;
  4870. +          int is_path;
  4871. +
  4872. +          expected_arg = rule->args[i];
  4873. +          expected_length = rule->arg_lens[i] & ~BUS_MATCH_ARG_IS_PATH;
  4874. +          is_path = (rule->arg_lens[i] & BUS_MATCH_ARG_IS_PATH) != 0;
  4875. +          
  4876. +          current_type = dbus_message_iter_get_arg_type (&iter);
  4877. +
  4878. +          if (expected_arg != NULL)
  4879. +            {
  4880. +              const char *actual_arg;
  4881. +              int actual_length;
  4882. +              
  4883. +              if (current_type != DBUS_TYPE_STRING)
  4884. +                return 0;
  4885. +
  4886. +              actual_arg = NULL;
  4887. +              dbus_message_iter_get_basic (&iter, &actual_arg);
  4888. +              _dbus_assert (actual_arg != NULL);
  4889. +
  4890. +              actual_length = strlen (actual_arg);
  4891. +
  4892. +              if (is_path)
  4893. +                {
  4894. +                  if (actual_length < expected_length &&
  4895. +                      actual_arg[actual_length - 1] != '/')
  4896. +                    return 0;
  4897. +
  4898. +                  if (expected_length < actual_length &&
  4899. +                      expected_arg[expected_length - 1] != '/')
  4900. +                    return 0;
  4901. +
  4902. +                  if (memcmp (actual_arg, expected_arg,
  4903. +                              MIN (actual_length, expected_length)) != 0)
  4904. +                    return 0;
  4905. +                }
  4906. +              else
  4907. +                {
  4908. +                  if (expected_length != actual_length ||
  4909. +                      memcmp (expected_arg, actual_arg, expected_length) != 0)
  4910. +                    return 0;
  4911. +                }
  4912. +
  4913. +            }
  4914. +          
  4915. +          if (current_type != DBUS_TYPE_INVALID)
  4916. +            dbus_message_iter_next (&iter);
  4917. +
  4918. +          ++i;
  4919. +        }
  4920. +    }
  4921. +#endif
  4922. +  
  4923. +  return 1;
  4924. +}
  4925. +
  4926. +static void
  4927. +get_recipients_from_list (struct hlist_head *rules,
  4928. +                          struct dbus_sock  *sender,
  4929. +                          struct dbus_sock  *addressed_recipient,
  4930. +                          const struct DBusMessage     *message,
  4931. +                          deliver_func_t deliver_func,
  4932. +                          void *user_data)
  4933. +{
  4934. +  struct hlist_node *cur;
  4935. +  BusMatchRule *rule;
  4936. +
  4937. +  if (rules == NULL)
  4938. +    return;
  4939. +
  4940. +  hlist_for_each_entry(rule, cur, rules, list)
  4941. +    {
  4942. +      char *s = match_rule_to_string (rule);
  4943. +
  4944. +
  4945. +      if (match_rule_matches (rule,
  4946. +                              sender, addressed_recipient, message,
  4947. +                              BUS_MATCH_MESSAGE_TYPE | BUS_MATCH_INTERFACE))
  4948. +        {
  4949. +          pr_debug ("  [YES] deliver to '%s' with match rule \"%s\"\n",
  4950. +              rule->matches_go_to->uniq_name ?
  4951. +              rule->matches_go_to->uniq_name : "(null)", s);
  4952. +          if (deliver_func)
  4953. +            deliver_func ((struct sock *)(rule->matches_go_to), user_data);
  4954. +        }
  4955. +      else
  4956. +        {
  4957. +          pr_debug ("  [NO]  deliver to '%s' with match rule \"%s\"\n",
  4958. +              rule->matches_go_to->uniq_name ?
  4959. +              rule->matches_go_to->uniq_name : "(null)", s);
  4960. +        }
  4961. +      kfree (s);
  4962. +    }
  4963. +}
  4964. +
  4965. +static struct hlist_head *
  4966. +bus_matchmaker_get_rules (BusMatchmaker *matchmaker,
  4967. +                          int            message_type,
  4968. +                          const char    *interface)
  4969. +{
  4970. +  static struct hlist_head empty = {0,};
  4971. +  RulePool *p;
  4972. +
  4973. +  WARN_ON (message_type < 0);
  4974. +  WARN_ON (message_type >= DBUS_NUM_MESSAGE_TYPES);
  4975. +
  4976. +  p = matchmaker->rules_by_type + message_type;
  4977. +
  4978. +  if (interface == NULL)
  4979. +    {
  4980. +      return &p->rules_without_iface;
  4981. +    }
  4982. +  else
  4983. +    {
  4984. +      BusMatchRule *rule = match_rule_search (&p->rules_by_iface,
  4985. +        interface);
  4986. +      if (rule)
  4987. +        return &rule->first;
  4988. +      else
  4989. +        return &empty;
  4990. +    }
  4991. +}
  4992. +
  4993. +void
  4994. +bus_matchmaker_get_recipients (BusMatchmaker   *matchmaker,
  4995. +                               struct dbus_sock  *sender,
  4996. +                               struct dbus_sock  *addressed_recipient,
  4997. +                               const struct DBusMessage     *message,
  4998. +                               deliver_func_t deliver_func,
  4999. +                               void *user_data)
  5000. +{
  5001. +  int type;
  5002. +  const char *interface;
  5003. +  struct hlist_head *neither, *just_type, *just_iface, *both;
  5004. +
  5005. +  type = message->type;
  5006. +  interface = message->interface;
  5007. +
  5008. +  neither = bus_matchmaker_get_rules (matchmaker, DBUS_MESSAGE_TYPE_INVALID,
  5009. +      NULL);
  5010. +  just_type = just_iface = both = NULL;
  5011. +
  5012. +  if (interface != NULL)
  5013. +    just_iface = bus_matchmaker_get_rules (matchmaker,
  5014. +        DBUS_MESSAGE_TYPE_INVALID, interface);
  5015. +
  5016. +  if (type > DBUS_MESSAGE_TYPE_INVALID && type < DBUS_NUM_MESSAGE_TYPES)
  5017. +    {
  5018. +      just_type = bus_matchmaker_get_rules (matchmaker, type, NULL);
  5019. +
  5020. +      if (interface != NULL)
  5021. +        both = bus_matchmaker_get_rules (matchmaker, type, interface);
  5022. +    }
  5023. +
  5024. +  get_recipients_from_list (neither, sender, addressed_recipient,
  5025. +      message, deliver_func, user_data);
  5026. +  get_recipients_from_list (just_iface, sender, addressed_recipient,
  5027. +      message, deliver_func, user_data);
  5028. +  get_recipients_from_list (just_type, sender, addressed_recipient,
  5029. +      message, deliver_func, user_data);
  5030. +  get_recipients_from_list (both, sender, addressed_recipient,
  5031. +      message, deliver_func, user_data);
  5032. +}
  5033. +
  5034. diff --git a/net/dbus/matchrule.h b/net/dbus/matchrule.h
  5035. new file mode 100644
  5036. index 0000000..d8de5d6
  5037. --- /dev/null
  5038. +++ b/net/dbus/matchrule.h
  5039. @@ -0,0 +1,92 @@
  5040. +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
  5041. +/* signals.h  Bus signal connection implementation
  5042. + *
  5043. + * Copyright (C) 2003  Red Hat, Inc.
  5044. + *
  5045. + * Licensed under the Academic Free License version 2.1
  5046. + *
  5047. + * This program is free software; you can redistribute it and/or modify
  5048. + * it under the terms of the GNU General Public License as published by
  5049. + * the Free Software Foundation; either version 2 of the License, or
  5050. + * (at your option) any later version.
  5051. + *
  5052. + * This program is distributed in the hope that it will be useful,
  5053. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5054. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  5055. + * GNU General Public License for more details.
  5056. + *
  5057. + * You should have received a copy of the GNU General Public License
  5058. + * along with this program; if not, write to the Free Software
  5059. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  5060. + *
  5061. + */
  5062. +
  5063. +#ifndef BUS_SIGNALS_H
  5064. +#define BUS_SIGNALS_H
  5065. +
  5066. +#include <net/af_dbus.h>
  5067. +#include <linux/list.h>
  5068. +
  5069. +#include "message.h"
  5070. +
  5071. +typedef struct BusMatchRule    BusMatchRule;
  5072. +typedef struct BusMatchmaker    BusMatchmaker;
  5073. +
  5074. +typedef enum
  5075. +{
  5076. +  BUS_MATCH_MESSAGE_TYPE = 1 << 0,
  5077. +  BUS_MATCH_INTERFACE    = 1 << 1,
  5078. +  BUS_MATCH_MEMBER       = 1 << 2,
  5079. +  BUS_MATCH_SENDER       = 1 << 3,
  5080. +  BUS_MATCH_DESTINATION  = 1 << 4,
  5081. +  BUS_MATCH_PATH         = 1 << 5,
  5082. +  BUS_MATCH_ARGS         = 1 << 6
  5083. +} BusMatchFlags;
  5084. +
  5085. +BusMatchRule* bus_match_rule_new   (struct dbus_sock *matches_go_to);
  5086. +BusMatchRule* bus_match_rule_ref   (BusMatchRule   *rule);
  5087. +void          bus_match_rule_unref (BusMatchRule   *rule);
  5088. +
  5089. +int bus_match_rule_set_message_type (BusMatchRule     *rule,
  5090. +                                             int               type);
  5091. +int bus_match_rule_set_interface    (BusMatchRule     *rule,
  5092. +                                             const char       *interface);
  5093. +int bus_match_rule_set_member       (BusMatchRule     *rule,
  5094. +                                             const char       *member);
  5095. +int bus_match_rule_set_sender       (BusMatchRule     *rule,
  5096. +                                             const char       *sender);
  5097. +int bus_match_rule_set_destination  (BusMatchRule     *rule,
  5098. +                                             const char       *destination);
  5099. +int bus_match_rule_set_path         (BusMatchRule     *rule,
  5100. +                                             const char       *path);
  5101. +int bus_match_rule_set_arg          (BusMatchRule     *rule,
  5102. +                                             int               arg,
  5103. +                                             const char       *value,
  5104. +                                             int       is_path);
  5105. +
  5106. +BusMatchRule* bus_match_rule_parse (struct dbus_sock   *matches_go_to,
  5107. +                                    const char         *rule_text);
  5108. +
  5109. +BusMatchmaker* bus_matchmaker_new   (void);
  5110. +BusMatchmaker* bus_matchmaker_ref   (BusMatchmaker *matchmaker);
  5111. +void           bus_matchmaker_unref (BusMatchmaker *matchmaker);
  5112. +
  5113. +int bus_matchmaker_add_rule             (BusMatchmaker   *matchmaker,
  5114. +                                                 BusMatchRule    *rule);
  5115. +void bus_matchmaker_remove_rule_by_value (BusMatchmaker   *matchmaker,
  5116. +                                                 BusMatchRule    *value);
  5117. +void        bus_matchmaker_remove_rule          (BusMatchmaker   *matchmaker,
  5118. +                                                 BusMatchRule    *rule);
  5119. +void        bus_matchmaker_disconnected         (BusMatchmaker   *matchmaker,
  5120. +                                                 struct dbus_sock  *connection);
  5121. +
  5122. +typedef void (*deliver_func_t) (struct sock *dest, void *user_data);
  5123. +
  5124. +void bus_matchmaker_get_recipients       (BusMatchmaker   *matchmaker,
  5125. +                                                 struct dbus_sock  *sender,
  5126. +                                                 struct dbus_sock  *addressed_recipient,
  5127. +                                                 const struct DBusMessage *message,
  5128. +                                                 deliver_func_t deliver_func,
  5129. +                                                 void *user_data);
  5130. +
  5131. +#endif /* BUS_SIGNALS_H */
  5132. diff --git a/net/dbus/message.c b/net/dbus/message.c
  5133. new file mode 100644
  5134. index 0000000..17233d3
  5135. --- /dev/null
  5136. +++ b/net/dbus/message.c
  5137. @@ -0,0 +1,274 @@
  5138. +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
  5139. +/* message.c  Basic D-Bus message parsing
  5140. + *
  5141. + * Copyright (C) 2010  Collabora Ltd
  5142. + * Authors:    Alban Crequy <alban.crequy@collabora.co.uk>
  5143. + * Copyright (C) 2002, 2003, 2004, 2005  Red Hat Inc.
  5144. + * Copyright (C) 2002, 2003  CodeFactory AB
  5145. + *
  5146. + * Licensed under the Academic Free License version 2.1
  5147. + *
  5148. + *
  5149. + * This program is free software; you can redistribute it and/or modify
  5150. + * it under the terms of the GNU General Public License as published by
  5151. + * the Free Software Foundation; either version 2 of the License, or
  5152. + * (at your option) any later version.
  5153. + *
  5154. + * This program is distributed in the hope that it will be useful,
  5155. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5156. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  5157. + * GNU General Public License for more details.
  5158. + *
  5159. + * You should have received a copy of the GNU General Public License
  5160. + * along with this program; if not, write to the Free Software
  5161. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  5162. + *
  5163. + */
  5164. +
  5165. +#include "message.h"
  5166. +#include "dbus-protocol.h"
  5167. +
  5168. +/**
  5169. + * Utility function to convert a machine-readable (not translated)
  5170. + * string into a D-Bus message type.
  5171. + *
  5172. + * @code
  5173. + *   "method_call"    -> DBUS_MESSAGE_TYPE_METHOD_CALL
  5174. + *   "method_return"  -> DBUS_MESSAGE_TYPE_METHOD_RETURN
  5175. + *   "signal"         -> DBUS_MESSAGE_TYPE_SIGNAL
  5176. + *   "error"          -> DBUS_MESSAGE_TYPE_ERROR
  5177. + *   anything else    -> DBUS_MESSAGE_TYPE_INVALID
  5178. + * @endcode
  5179. + *
  5180. + */
  5181. +int
  5182. +dbus_message_type_from_string (const char *type_str)
  5183. +{
  5184. +  if (strcmp (type_str, "method_call") == 0)
  5185. +    return DBUS_MESSAGE_TYPE_METHOD_CALL;
  5186. +  if (strcmp (type_str, "method_return") == 0)
  5187. +    return DBUS_MESSAGE_TYPE_METHOD_RETURN;
  5188. +  else if (strcmp (type_str, "signal") == 0)
  5189. +    return DBUS_MESSAGE_TYPE_SIGNAL;
  5190. +  else if (strcmp (type_str, "error") == 0)
  5191. +    return DBUS_MESSAGE_TYPE_ERROR;
  5192. +  else
  5193. +    return DBUS_MESSAGE_TYPE_INVALID;
  5194. +}
  5195. +
  5196. +/**
  5197. + * Utility function to convert a D-Bus message type into a
  5198. + * machine-readable string (not translated).
  5199. + *
  5200. + * @code
  5201. + *   DBUS_MESSAGE_TYPE_METHOD_CALL    -> "method_call"
  5202. + *   DBUS_MESSAGE_TYPE_METHOD_RETURN  -> "method_return"
  5203. + *   DBUS_MESSAGE_TYPE_SIGNAL         -> "signal"
  5204. + *   DBUS_MESSAGE_TYPE_ERROR          -> "error"
  5205. + *   DBUS_MESSAGE_TYPE_INVALID        -> "invalid"
  5206. + * @endcode
  5207. + *
  5208. + */
  5209. +const char *
  5210. +dbus_message_type_to_string (int type)
  5211. +{
  5212. +  switch (type)
  5213. +    {
  5214. +    case DBUS_MESSAGE_TYPE_METHOD_CALL:
  5215. +      return "method_call";
  5216. +    case DBUS_MESSAGE_TYPE_METHOD_RETURN:
  5217. +      return "method_return";
  5218. +    case DBUS_MESSAGE_TYPE_SIGNAL:
  5219. +      return "signal";
  5220. +    case DBUS_MESSAGE_TYPE_ERROR:
  5221. +      return "error";
  5222. +    default:
  5223. +      return "invalid";
  5224. +    }
  5225. +}
  5226. +
  5227. +int dbus_message_parse(unsigned char *message, size_t len,
  5228. +    struct DBusMessage *dbus_message)
  5229. +{
  5230. +       unsigned char *cur;
  5231. +       int array_header_len;
  5232. +
  5233. +       dbus_message->message = message;
  5234. +
  5235. +       if (len < 4 + 4 + 4 + 4 || message[1] == 0 || message[1] > 4) {
  5236. +               return -EINVAL;
  5237. +       }
  5238. +       dbus_message->type = message[1];
  5239. +       dbus_message->body_length = *((u32 *)(message + 4));
  5240. +       cur = message + 12;
  5241. +       array_header_len = *(u32 *)cur;
  5242. +       dbus_message->len_offset = 12;
  5243. +       cur += 4;
  5244. +       while (cur < message + len
  5245. +           && cur < message + 12 + 4 + array_header_len) {
  5246. +               int header_code;
  5247. +               int signature_len;
  5248. +               unsigned char *signature;
  5249. +               int str_len;
  5250. +               unsigned char *str;
  5251. +
  5252. +               /* D-Bus alignment craziness */
  5253. +               if ((cur - message) % 8 != 0)
  5254. +                       cur += 8 - (cur - message) % 8;
  5255. +
  5256. +               header_code = *(char *)cur;
  5257. +               cur++;
  5258. +               signature_len = *(char *)cur;
  5259. +               /* All header fields of the current D-Bus spec have a simple
  5260. +                * type, either o, s, g, or u */
  5261. +               if (signature_len != 1)
  5262. +                       return -EINVAL;
  5263. +               cur++;
  5264. +               signature = cur;
  5265. +               cur += signature_len + 1;
  5266. +               if (signature[0] != 'o' &&
  5267. +                   signature[0] != 's' &&
  5268. +                   signature[0] != 'g' &&
  5269. +                   signature[0] != 'u')
  5270. +                 return -EINVAL;
  5271. +
  5272. +               if (signature[0] == 'u') {
  5273. +                       cur += 4;
  5274. +                       continue;
  5275. +               }
  5276. +
  5277. +               if (signature[0] != 'g') {
  5278. +                       str_len = *(u32 *)cur;
  5279. +                       cur += 4;
  5280. +               } else {
  5281. +                       str_len = *(char *)cur;
  5282. +                       cur += 1;
  5283. +               }
  5284. +
  5285. +               str = cur;
  5286. +               switch (header_code) {
  5287. +                       case 1: dbus_message->path = str;
  5288. +                               break;
  5289. +                       case 2: dbus_message->interface = str;
  5290. +                               break;
  5291. +                       case 3: dbus_message->member = str;
  5292. +                               break;
  5293. +                       case 6: dbus_message->destination = str;
  5294. +                               break;
  5295. +                       case 7: dbus_message->sender = str;
  5296. +                               break;
  5297. +                       case 8: dbus_message->body_signature = str;
  5298. +                               break;
  5299. +               }
  5300. +               cur += str_len + 1;
  5301. +       }
  5302. +
  5303. +       dbus_message->padding_end = (8 - (cur - message) % 8) % 8;
  5304. +
  5305. +        /* Jump to body D-Bus alignment craziness */
  5306. +        if ((cur - message) % 8 != 0)
  5307. +               cur += 8 - (cur - message) % 8;
  5308. +       dbus_message->new_header_offset = cur - message;
  5309. +
  5310. +       if (dbus_message->new_header_offset
  5311. +            + dbus_message->body_length != len) {
  5312. +               pr_warning("Message truncated? "
  5313. +                    "Header %d + Body %d != Length %zd\n",
  5314. +                    dbus_message->new_header_offset,
  5315. +                    dbus_message->body_length, len);
  5316. +               return -EINVAL;
  5317. +       }
  5318. +
  5319. +       if (dbus_message->body_signature &&
  5320. +            dbus_message->body_signature[0] == 's') {
  5321. +               int str_len;
  5322. +                str_len = *(u32 *)cur;
  5323. +                cur += 4;
  5324. +               dbus_message->arg0 = cur;
  5325. +               cur += str_len + 1;
  5326. +       }
  5327. +
  5328. +        if ((cur - message) % 4 != 0)
  5329. +               cur += 4 - (cur - message) % 4;
  5330. +
  5331. +       if (dbus_message->body_signature &&
  5332. +            dbus_message->body_signature[0] == 's' &&
  5333. +            dbus_message->body_signature[1] == 's') {
  5334. +               int str_len;
  5335. +                str_len = *(u32 *)cur;
  5336. +                cur += 4;
  5337. +               dbus_message->arg1 = cur;
  5338. +               cur += str_len + 1;
  5339. +       }
  5340. +
  5341. +        if ((cur - message) % 4 != 0)
  5342. +               cur += 4 - (cur - message) % 4;
  5343. +
  5344. +       if (dbus_message->body_signature &&
  5345. +            dbus_message->body_signature[0] == 's' &&
  5346. +            dbus_message->body_signature[1] == 's' &&
  5347. +            dbus_message->body_signature[2] == 's') {
  5348. +               int str_len;
  5349. +                str_len = *(u32 *)cur;
  5350. +                cur += 4;
  5351. +               dbus_message->arg2 = cur;
  5352. +               cur += str_len + 1;
  5353. +       }
  5354. +
  5355. +        if ((cur - message) % 4 != 0)
  5356. +               cur += 4 - (cur - message) % 4;
  5357. +
  5358. +       return 0;
  5359. +}
  5360. +
  5361. +
  5362. +int
  5363. +dbus_message_add_sender(struct DBusMessage *dbus_message,
  5364. +    const char *sender, gfp_t gfp_flags)
  5365. +{
  5366. +       unsigned char *message = dbus_message->message;
  5367. +       unsigned char *new_message;
  5368. +       int added_size_not_aligned = 1 + 3 + 4 +
  5369. +          strlen(sender) + 1;
  5370. +       int added_size = added_size_not_aligned
  5371. +          + (8 - added_size_not_aligned % 8) % 8;
  5372. +
  5373. +       dbus_message->new_len = dbus_message->len + added_size;
  5374. +       new_message = kmalloc(dbus_message->new_len, gfp_flags);
  5375. +        if (!new_message)
  5376. +               return -ENOMEM;
  5377. +
  5378. +       memcpy(new_message, message, dbus_message->new_header_offset);
  5379. +       *(char*)(new_message + dbus_message->new_header_offset)
  5380. +          = 7;
  5381. +       *(char*)(new_message + dbus_message->new_header_offset + 1)
  5382. +          = 1;
  5383. +       *(char*)(new_message + dbus_message->new_header_offset + 2)
  5384. +          = 's';
  5385. +       *(char*)(new_message + dbus_message->new_header_offset + 3)
  5386. +          = '\0';
  5387. +       *(u32*)(new_message + dbus_message->new_header_offset + 4)
  5388. +          = strlen(sender);
  5389. +
  5390. +       BUG_ON(dbus_message->sender != NULL);
  5391. +       dbus_message->sender = new_message + dbus_message->new_header_offset
  5392. +            + 1 + 3 + 4;
  5393. +       strcpy(dbus_message->sender, sender);
  5394. +       memset(new_message + dbus_message->new_header_offset
  5395. +            + added_size_not_aligned, 0,
  5396. +            added_size - added_size_not_aligned);
  5397. +       memcpy(new_message + dbus_message->new_header_offset
  5398. +            + added_size,
  5399. +            message + dbus_message->new_header_offset,
  5400. +            dbus_message->len - dbus_message->new_header_offset);
  5401. +
  5402. +       *(u32*)(new_message + dbus_message->len_offset) =
  5403. +          *(u32*)(new_message + dbus_message->len_offset) +
  5404. +          dbus_message->padding_end + added_size_not_aligned;
  5405. +
  5406. +       kfree(message);
  5407. +       dbus_message_parse(new_message, dbus_message->new_len, dbus_message);
  5408. +
  5409. +       return 0;
  5410. +}
  5411. +
  5412. diff --git a/net/dbus/message.h b/net/dbus/message.h
  5413. new file mode 100644
  5414. index 0000000..263e5d5
  5415. --- /dev/null
  5416. +++ b/net/dbus/message.h
  5417. @@ -0,0 +1,64 @@
  5418. +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
  5419. +/* message.h  Basic D-Bus message parsing
  5420. + *
  5421. + * Copyright (C) 2010  Collabora Ltd
  5422. + *
  5423. + * This program is free software; you can redistribute it and/or modify
  5424. + * it under the terms of the GNU General Public License as published by
  5425. + * the Free Software Foundation; either version 2 of the License, or
  5426. + * (at your option) any later version.
  5427. + *
  5428. + * This program is distributed in the hope that it will be useful,
  5429. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5430. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  5431. + * GNU General Public License for more details.
  5432. + *
  5433. + * You should have received a copy of the GNU General Public License
  5434. + * along with this program; if not, write to the Free Software
  5435. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  5436. + *
  5437. + */
  5438. +
  5439. +#ifndef DBUS_MESSAGE_H
  5440. +#define DBUS_MESSAGE_H
  5441. +
  5442. +#include <net/af_dbus.h>
  5443. +#include <linux/list.h>
  5444. +
  5445. +/* No need to implement a feature-complete parser. It only implement what is
  5446. + * needed by the bus. */
  5447. +struct DBusMessage {
  5448. +  char *message;
  5449. +  size_t len;
  5450. +  size_t new_len;
  5451. +
  5452. +  /* direct pointers to the fields */
  5453. +  int type;
  5454. +  char *path;
  5455. +  char *interface;
  5456. +  char *member;
  5457. +  char *destination;
  5458. +  char *sender;
  5459. +  char *body_signature;
  5460. +  int body_length;
  5461. +  char *arg0;
  5462. +  char *arg1;
  5463. +  char *arg2;
  5464. +
  5465. +  /* How to add the 'sender' field in the headers */
  5466. +  int new_header_offset;
  5467. +  int len_offset;
  5468. +  int padding_end;
  5469. +};
  5470. +
  5471. +int dbus_message_type_from_string (const char *type_str);
  5472. +
  5473. +const char *dbus_message_type_to_string (int type);
  5474. +
  5475. +int dbus_message_parse(unsigned char *message, size_t len,
  5476. +    struct DBusMessage *dbus_message);
  5477. +
  5478. +int dbus_message_add_sender(struct DBusMessage *dbus_message,
  5479. +    const char *sender, gfp_t gfp_flags);
  5480. +
  5481. +#endif /* DBUS_MESSAGE_H */
  5482. diff --git a/net/dbus/sysctl_net_dbus.c b/net/dbus/sysctl_net_dbus.c
  5483. new file mode 100644
  5484. index 0000000..1f5cd15
  5485. --- /dev/null
  5486. +++ b/net/dbus/sysctl_net_dbus.c
  5487. @@ -0,0 +1,62 @@
  5488. +/*
  5489. + * NET4:       Sysctl interface to net af_dbus subsystem.
  5490. + *
  5491. + * Authors:    Mike Shaver.
  5492. + *
  5493. + *             This program is free software; you can redistribute it and/or
  5494. + *             modify it under the terms of the GNU General Public License
  5495. + *             as published by the Free Software Foundation; either version
  5496. + *             2 of the License, or (at your option) any later version.
  5497. + */
  5498. +
  5499. +#include <linux/mm.h>
  5500. +#include <linux/sysctl.h>
  5501. +
  5502. +#include <net/af_dbus.h>
  5503. +
  5504. +static ctl_table dbus_table[] = {
  5505. +       {
  5506. +               .procname       = "max_dgram_qlen",
  5507. +               .data           = &init_net.unx.sysctl_max_dgram_qlen,
  5508. +               .maxlen         = sizeof(int),
  5509. +               .mode           = 0644,
  5510. +               .proc_handler   = proc_dointvec
  5511. +       },
  5512. +       { }
  5513. +};
  5514. +
  5515. +static struct ctl_path dbus_path[] = {
  5516. +       { .procname = "net", },
  5517. +       { .procname = "dbus", },
  5518. +       { },
  5519. +};
  5520. +
  5521. +int dbus_sysctl_register(struct net *net)
  5522. +{
  5523. +       struct ctl_table *table;
  5524. +
  5525. +       table = kmemdup(dbus_table, sizeof(dbus_table), GFP_KERNEL);
  5526. +       if (table == NULL)
  5527. +               goto err_alloc;
  5528. +
  5529. +       table[0].data = &net->unx.sysctl_max_dgram_qlen;
  5530. +       net->unx.ctl = register_net_sysctl_table(net, dbus_path, table);
  5531. +       if (net->unx.ctl == NULL)
  5532. +               goto err_reg;
  5533. +
  5534. +       return 0;
  5535. +
  5536. +err_reg:
  5537. +       kfree(table);
  5538. +err_alloc:
  5539. +       return -ENOMEM;
  5540. +}
  5541. +
  5542. +void dbus_sysctl_unregister(struct net *net)
  5543. +{
  5544. +       struct ctl_table *table;
  5545. +
  5546. +       table = net->unx.ctl->ctl_table_arg;
  5547. +       unregister_sysctl_table(net->unx.ctl);
  5548. +       kfree(table);
  5549. +}
  5550. diff --git a/security/capability.c b/security/capability.c
  5551. index 8168e3e..377d0b4 100644
  5552. --- a/security/capability.c
  5553. +++ b/security/capability.c
  5554. @@ -554,6 +554,17 @@ static int cap_unix_may_send(struct socket *sock, struct socket *other)
  5555.         return 0;
  5556.  }
  5557.  
  5558. +static int cap_dbus_stream_connect(struct socket *sock, struct socket *other,
  5559. +                                   struct sock *newsk)
  5560. +{
  5561. +        return 0;
  5562. +}
  5563. +
  5564. +static int cap_dbus_may_send(struct socket *sock, struct socket *other)
  5565. +{
  5566. +        return 0;
  5567. +}
  5568. +
  5569.  static int cap_socket_create(int family, int type, int protocol, int kern)
  5570.  {
  5571.         return 0;
  5572. @@ -994,6 +1005,8 @@ void __init security_fixup_ops(struct security_operations *ops)
  5573.  #ifdef CONFIG_SECURITY_NETWORK
  5574.         set_to_cap_if_null(ops, unix_stream_connect);
  5575.         set_to_cap_if_null(ops, unix_may_send);
  5576. +       set_to_cap_if_null(ops, dbus_stream_connect);
  5577. +       set_to_cap_if_null(ops, dbus_may_send);
  5578.         set_to_cap_if_null(ops, socket_create);
  5579.         set_to_cap_if_null(ops, socket_post_create);
  5580.         set_to_cap_if_null(ops, socket_bind);
  5581. diff --git a/security/security.c b/security/security.c
  5582. index 351942a..5516f59 100644
  5583. --- a/security/security.c
  5584. +++ b/security/security.c
  5585. @@ -995,6 +995,19 @@ int security_unix_may_send(struct socket *sock,  struct socket *other)
  5586.  }
  5587.  EXPORT_SYMBOL(security_unix_may_send);
  5588.  
  5589. +int security_dbus_stream_connect(struct socket *sock, struct socket *other,
  5590. +                                 struct sock *newsk)
  5591. +{
  5592. +        return security_ops->dbus_stream_connect(sock, other, newsk);
  5593. +}
  5594. +EXPORT_SYMBOL(security_dbus_stream_connect);
  5595. +
  5596. +int security_dbus_may_send(struct socket *sock,  struct socket *other)
  5597. +{
  5598. +       return security_ops->dbus_may_send(sock, other);
  5599. +}
  5600. +EXPORT_SYMBOL(security_dbus_may_send);
  5601. +
  5602.  int security_socket_create(int family, int type, int protocol, int kern)
  5603.  {
  5604.         return security_ops->socket_create(family, type, protocol, kern);
  5605. diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
  5606. index 5c9f25b..11dfb51 100644
  5607. --- a/security/selinux/hooks.c
  5608. +++ b/security/selinux/hooks.c
  5609. @@ -65,6 +65,7 @@
  5610.  #include <linux/quota.h>
  5611.  #include <linux/un.h>          /* for Unix socket types */
  5612.  #include <net/af_unix.h>       /* for Unix socket types */
  5613. +#include <net/af_dbus.h>       /* for DBus socket types */
  5614.  #include <linux/parser.h>
  5615.  #include <linux/nfs_mount.h>
  5616.  #include <net/ipv6.h>
  5617. @@ -4032,6 +4033,64 @@ static int selinux_socket_unix_may_send(struct socket *sock,
  5618.         return 0;
  5619.  }
  5620.  
  5621. +static int selinux_socket_dbus_stream_connect(struct socket *sock,
  5622. +                                              struct socket *other,
  5623. +                                              struct sock *newsk)
  5624. +{
  5625. +        struct sk_security_struct *ssec;
  5626. +        struct inode_security_struct *isec;
  5627. +        struct inode_security_struct *other_isec;
  5628. +        struct common_audit_data ad;
  5629. +        int err;
  5630. +
  5631. +        isec = SOCK_INODE(sock)->i_security;
  5632. +        other_isec = SOCK_INODE(other)->i_security;
  5633. +
  5634. +        COMMON_AUDIT_DATA_INIT(&ad, NET);
  5635. +        ad.u.net.sk = other->sk;
  5636. +
  5637. +        err = avc_has_perm(isec->sid, other_isec->sid,
  5638. +                           isec->sclass,
  5639. +                           UNIX_STREAM_SOCKET__CONNECTTO, &ad); //FIXME!!!
  5640. +        if (err)
  5641. +                return err;
  5642. +
  5643. +        /* connecting socket */
  5644. +        ssec = sock->sk->sk_security;
  5645. +        ssec->peer_sid = other_isec->sid;
  5646. +
  5647. +        /* server child socket */
  5648. +        ssec = newsk->sk_security;
  5649. +        ssec->peer_sid = isec->sid;
  5650. +        err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid)
  5651. +;
  5652. +
  5653. +        return err;
  5654. +}
  5655. +
  5656. +
  5657. +static int selinux_socket_dbus_may_send(struct socket *sock,
  5658. +                                        struct socket *other)
  5659. +{
  5660. +       struct inode_security_struct *isec;
  5661. +       struct inode_security_struct *other_isec;
  5662. +       struct common_audit_data ad;
  5663. +       int err;
  5664. +
  5665. +       isec = SOCK_INODE(sock)->i_security;
  5666. +       other_isec = SOCK_INODE(other)->i_security;
  5667. +
  5668. +       COMMON_AUDIT_DATA_INIT(&ad, NET);
  5669. +       ad.u.net.sk = other->sk;
  5670. +
  5671. +       err = avc_has_perm(isec->sid, other_isec->sid,
  5672. +                          isec->sclass, SOCKET__SENDTO, &ad);
  5673. +       if (err)
  5674. +               return err;
  5675. +
  5676. +       return 0;
  5677. +}
  5678. +
  5679.  static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
  5680.                                     u32 peer_sid,
  5681.                                     struct common_audit_data *ad)
  5682. @@ -5565,6 +5624,8 @@ static struct security_operations selinux_ops = {
  5683.  
  5684.         .unix_stream_connect =          selinux_socket_unix_stream_connect,
  5685.         .unix_may_send =                selinux_socket_unix_may_send,
  5686. +       .dbus_stream_connect =          selinux_socket_dbus_stream_connect,
  5687. +       .dbus_may_send =                selinux_socket_dbus_may_send,
  5688.  
  5689.         .socket_create =                selinux_socket_create,
  5690.         .socket_post_create =           selinux_socket_post_create,
  5691. --- a/include/net/af_dbus.h
  5692. +++ b/include/net/af_dbus.h
  5693. @@ -58,7 +58,7 @@
  5694.         spinlock_t              lock;
  5695.         unsigned int            gc_candidate : 1;
  5696.         unsigned int            gc_maybe_cycle : 1;
  5697. -       struct socket_wq        peer_wq;
  5698. +       wait_queue_head_t       peer_wait;
  5699.  
  5700.         struct dbus_sock_priv   *priv;
  5701.         unsigned int    daemon_side;
  5702. @@ -72,8 +72,6 @@
  5703.  };
  5704.  #define dbus_sk(__sk) ((struct dbus_sock *)__sk)
  5705.  
  5706. -#define peer_wait peer_wq.wait
  5707. -
  5708.  #ifdef CONFIG_SYSCTL
  5709.  extern int dbus_sysctl_register(struct net *net);
  5710.  extern void dbus_sysctl_unregister(struct net *net);
  5711. --- a/net/dbus/af_dbus.c
  5712. +++ b/net/dbus/af_dbus.c
  5713. @@ -315,16 +315,13 @@
  5714.  
  5715.  static void dbus_write_space(struct sock *sk)
  5716.  {
  5717. -       struct socket_wq *wq;
  5718. -
  5719. -       rcu_read_lock();
  5720. +       read_lock(&sk->sk_callback_lock);
  5721.         if (dbus_writable(sk)) {
  5722. -               wq = rcu_dereference(sk->sk_wq);
  5723. -               if (wq_has_sleeper(wq))
  5724. -                       wake_up_interruptible_sync(&wq->wait);
  5725. +               if (sk_has_sleeper(sk))
  5726. +                       wake_up_interruptible_sync(sk->sk_sleep);
  5727.                 sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
  5728.         }
  5729. -       rcu_read_unlock();
  5730. +       read_unlock(&sk->sk_callback_lock);
  5731.  }
  5732.  
  5733.  static void dbus_sock_destructor(struct sock *sk)
  5734. @@ -586,8 +583,7 @@
  5735.         return sk;
  5736.  }
  5737.  
  5738. -static int dbus_create(struct net *net, struct socket *sock, int protocol,
  5739. -                      int kern)
  5740. +static int dbus_create(struct net *net, struct socket *sock, int protocol)
  5741.  {
  5742.         if (protocol && protocol != PF_DBUS)
  5743.                 return -EPROTONOSUPPORT;
  5744. @@ -1007,7 +1003,7 @@
  5745.         current_euid_egid(&newsk->sk_peercred.uid, &newsk->sk_peercred.gid);
  5746.         newu = dbus_sk(newsk);
  5747.         newu->daemon_side       = 1;
  5748. -       newsk->sk_wq            = &newu->peer_wq;
  5749. +       newsk->sk_sleep         = &newu->peer_wait;
  5750.         otheru = dbus_sk(other);
  5751.         newu->bus = otheru->bus;
  5752.         u->bus = otheru->bus;
  5753. @@ -1126,7 +1122,7 @@
  5754.  {
  5755.         struct sock *sk = sock->sk;
  5756.         struct dbus_sock *u;
  5757. -       DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, uaddr);
  5758. +       struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
  5759.         int err = 0;
  5760.  
  5761.         if (peer) {
  5762. @@ -1604,7 +1600,7 @@
  5763.         dbus_state_lock(sk);
  5764.  
  5765.         for (;;) {
  5766. -               prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
  5767. +               prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
  5768.  
  5769.                 if (!skb_queue_empty(&sk->sk_receive_queue) ||
  5770.                     sk->sk_err ||
  5771. @@ -1620,7 +1616,7 @@
  5772.                 clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
  5773.         }
  5774.  
  5775. -       finish_wait(sk_sleep(sk), &wait);
  5776. +       finish_wait(sk->sk_sleep, &wait);
  5777.         dbus_state_unlock(sk);
  5778.         return timeo;
  5779.  }
  5780. @@ -1857,7 +1853,7 @@
  5781.         struct sock *sk = sock->sk;
  5782.         unsigned int mask;
  5783.  
  5784. -       sock_poll_wait(file, sk_sleep(sk), wait);
  5785. +       sock_poll_wait(file, sk->sk_sleep, wait);
  5786.         mask = 0;
  5787.  
  5788.         /* exceptional events? */
Add Comment
Please, Sign In to add comment