/net/ipv4/netfilter/ipt_owner.c

https://bitbucket.org/abioy/linux · C · 204 lines · 173 code · 26 blank · 5 comment · 33 complexity · b41117c322034207a4f51ccc0678d1de MD5 · raw file

  1. /* Kernel module to match various things tied to sockets associated with
  2. locally generated outgoing packets.
  3. Copyright (C) 2000 Marc Boucher
  4. */
  5. #include <linux/module.h>
  6. #include <linux/skbuff.h>
  7. #include <linux/file.h>
  8. #include <net/sock.h>
  9. #include <linux/netfilter_ipv4/ipt_owner.h>
  10. #include <linux/netfilter_ipv4/ip_tables.h>
  11. MODULE_LICENSE("GPL");
  12. MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
  13. MODULE_DESCRIPTION("iptables owner match");
  14. static int
  15. match_comm(const struct sk_buff *skb, const char *comm)
  16. {
  17. struct task_struct *g, *p;
  18. struct files_struct *files;
  19. int i;
  20. read_lock(&tasklist_lock);
  21. do_each_thread(g, p) {
  22. if(strncmp(p->comm, comm, sizeof(p->comm)))
  23. continue;
  24. task_lock(p);
  25. files = p->files;
  26. if(files) {
  27. spin_lock(&files->file_lock);
  28. for (i=0; i < files->max_fds; i++) {
  29. if (fcheck_files(files, i) ==
  30. skb->sk->sk_socket->file) {
  31. spin_unlock(&files->file_lock);
  32. task_unlock(p);
  33. read_unlock(&tasklist_lock);
  34. return 1;
  35. }
  36. }
  37. spin_unlock(&files->file_lock);
  38. }
  39. task_unlock(p);
  40. } while_each_thread(g, p);
  41. read_unlock(&tasklist_lock);
  42. return 0;
  43. }
  44. static int
  45. match_pid(const struct sk_buff *skb, pid_t pid)
  46. {
  47. struct task_struct *p;
  48. struct files_struct *files;
  49. int i;
  50. read_lock(&tasklist_lock);
  51. p = find_task_by_pid(pid);
  52. if (!p)
  53. goto out;
  54. task_lock(p);
  55. files = p->files;
  56. if(files) {
  57. spin_lock(&files->file_lock);
  58. for (i=0; i < files->max_fds; i++) {
  59. if (fcheck_files(files, i) ==
  60. skb->sk->sk_socket->file) {
  61. spin_unlock(&files->file_lock);
  62. task_unlock(p);
  63. read_unlock(&tasklist_lock);
  64. return 1;
  65. }
  66. }
  67. spin_unlock(&files->file_lock);
  68. }
  69. task_unlock(p);
  70. out:
  71. read_unlock(&tasklist_lock);
  72. return 0;
  73. }
  74. static int
  75. match_sid(const struct sk_buff *skb, pid_t sid)
  76. {
  77. struct task_struct *g, *p;
  78. struct file *file = skb->sk->sk_socket->file;
  79. int i, found=0;
  80. read_lock(&tasklist_lock);
  81. do_each_thread(g, p) {
  82. struct files_struct *files;
  83. if (p->session != sid)
  84. continue;
  85. task_lock(p);
  86. files = p->files;
  87. if (files) {
  88. spin_lock(&files->file_lock);
  89. for (i=0; i < files->max_fds; i++) {
  90. if (fcheck_files(files, i) == file) {
  91. found = 1;
  92. break;
  93. }
  94. }
  95. spin_unlock(&files->file_lock);
  96. }
  97. task_unlock(p);
  98. if (found)
  99. goto out;
  100. } while_each_thread(g, p);
  101. out:
  102. read_unlock(&tasklist_lock);
  103. return found;
  104. }
  105. static int
  106. match(const struct sk_buff *skb,
  107. const struct net_device *in,
  108. const struct net_device *out,
  109. const void *matchinfo,
  110. int offset,
  111. int *hotdrop)
  112. {
  113. const struct ipt_owner_info *info = matchinfo;
  114. if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
  115. return 0;
  116. if(info->match & IPT_OWNER_UID) {
  117. if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
  118. !!(info->invert & IPT_OWNER_UID))
  119. return 0;
  120. }
  121. if(info->match & IPT_OWNER_GID) {
  122. if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
  123. !!(info->invert & IPT_OWNER_GID))
  124. return 0;
  125. }
  126. if(info->match & IPT_OWNER_PID) {
  127. if (!match_pid(skb, info->pid) ^
  128. !!(info->invert & IPT_OWNER_PID))
  129. return 0;
  130. }
  131. if(info->match & IPT_OWNER_SID) {
  132. if (!match_sid(skb, info->sid) ^
  133. !!(info->invert & IPT_OWNER_SID))
  134. return 0;
  135. }
  136. if(info->match & IPT_OWNER_COMM) {
  137. if (!match_comm(skb, info->comm) ^
  138. !!(info->invert & IPT_OWNER_COMM))
  139. return 0;
  140. }
  141. return 1;
  142. }
  143. static int
  144. checkentry(const char *tablename,
  145. const struct ipt_ip *ip,
  146. void *matchinfo,
  147. unsigned int matchsize,
  148. unsigned int hook_mask)
  149. {
  150. if (hook_mask
  151. & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
  152. printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
  153. return 0;
  154. }
  155. if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
  156. printk("Matchsize %u != %Zu\n", matchsize,
  157. IPT_ALIGN(sizeof(struct ipt_owner_info)));
  158. return 0;
  159. }
  160. return 1;
  161. }
  162. static struct ipt_match owner_match = {
  163. .name = "owner",
  164. .match = &match,
  165. .checkentry = &checkentry,
  166. .me = THIS_MODULE,
  167. };
  168. static int __init init(void)
  169. {
  170. return ipt_register_match(&owner_match);
  171. }
  172. static void __exit fini(void)
  173. {
  174. ipt_unregister_match(&owner_match);
  175. }
  176. module_init(init);
  177. module_exit(fini);