オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Diff of /branches/ccs-patch/fs/tomoyo_network.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2030 by kumaneko, Thu Jan 1 01:40:06 2009 UTC revision 2037 by kumaneko, Mon Jan 5 05:56:56 2009 UTC
# Line 5  Line 5 
5   *   *
6   * Copyright (C) 2005-2009  NTT DATA CORPORATION   * Copyright (C) 2005-2009  NTT DATA CORPORATION
7   *   *
8   * Version: 1.6.6-pre   2008/12/24   * Version: 1.6.6-pre   2009/01/05
9   *   *
10   * This file is applicable to both 2.4.30 and 2.6.11 and later.   * This file is applicable to both 2.4.30 and 2.6.11 and later.
11   * See README.ccs for ChangeLog.   * See README.ccs for ChangeLog.
# Line 19  Line 19 
19  #include <linux/inet.h>  #include <linux/inet.h>
20  #include <linux/in.h>  #include <linux/in.h>
21  #include <linux/in6.h>  #include <linux/in6.h>
22    #include <net/ip.h>
23    #include <net/ipv6.h>
24    #include <net/udp.h>
25    
26    /* Index numbers for Network Controls. */
27    enum ccs_network_acl_index {
28            NETWORK_ACL_UDP_BIND,
29            NETWORK_ACL_UDP_CONNECT,
30            NETWORK_ACL_TCP_BIND,
31            NETWORK_ACL_TCP_LISTEN,
32            NETWORK_ACL_TCP_CONNECT,
33            NETWORK_ACL_TCP_ACCEPT,
34            NETWORK_ACL_RAW_BIND,
35            NETWORK_ACL_RAW_CONNECT
36    };
37    
38  /**  /**
39   * ccs_audit_network_log - Audit network log.   * ccs_audit_network_log - Audit network log.
# Line 770  int ccs_write_network_policy(char *data, Line 785  int ccs_write_network_policy(char *data,
785   *   *
786   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
787   */   */
788  int ccs_check_network_listen_acl(const _Bool is_ipv6, const u8 *address,  static inline int ccs_check_network_listen_acl(const bool is_ipv6,
789                                   const u16 port)                                                 const u8 *address,
790                                                   const u16 port)
791  {  {
792          return ccs_check_network_entry(is_ipv6, NETWORK_ACL_TCP_LISTEN,          return ccs_check_network_entry(is_ipv6, NETWORK_ACL_TCP_LISTEN,
793                                         (const u32 *) address, ntohs(port));                                         (const u32 *) address, ntohs(port));
# Line 787  int ccs_check_network_listen_acl(const _ Line 803  int ccs_check_network_listen_acl(const _
803   *   *
804   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
805   */   */
806  int ccs_check_network_connect_acl(const _Bool is_ipv6, const int sock_type,  static inline int ccs_check_network_connect_acl(const bool is_ipv6,
807                                    const u8 *address, const u16 port)                                                  const int sock_type,
808                                                    const u8 *address,
809                                                    const u16 port)
810  {  {
811          u8 operation;          u8 operation;
812          switch (sock_type) {          switch (sock_type) {
# Line 815  int ccs_check_network_connect_acl(const Line 833  int ccs_check_network_connect_acl(const
833   *   *
834   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
835   */   */
836  int ccs_check_network_bind_acl(const _Bool is_ipv6, const int sock_type,  static int ccs_check_network_bind_acl(const bool is_ipv6, const int sock_type,
837                                 const u8 *address, const u16 port)                                        const u8 *address, const u16 port)
838  {  {
839          u8 operation;          u8 operation;
840          switch (sock_type) {          switch (sock_type) {
# Line 842  int ccs_check_network_bind_acl(const _Bo Line 860  int ccs_check_network_bind_acl(const _Bo
860   *   *
861   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
862   */   */
863  int ccs_check_network_accept_acl(const _Bool is_ipv6, const u8 *address,  static inline int ccs_check_network_accept_acl(const bool is_ipv6,
864                                   const u16 port)                                                 const u8 *address,
865                                                   const u16 port)
866  {  {
867          int retval;          int retval;
868          current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
# Line 863  int ccs_check_network_accept_acl(const _ Line 882  int ccs_check_network_accept_acl(const _
882   *   *
883   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
884   */   */
885  int ccs_check_network_sendmsg_acl(const _Bool is_ipv6, const int sock_type,  static inline int ccs_check_network_sendmsg_acl(const bool is_ipv6,
886                                    const u8 *address, const u16 port)                                                  const int sock_type,
887                                                    const u8 *address,
888                                                    const u16 port)
889  {  {
890          u8 operation;          u8 operation;
891          if (sock_type == SOCK_DGRAM)          if (sock_type == SOCK_DGRAM)
# Line 885  int ccs_check_network_sendmsg_acl(const Line 906  int ccs_check_network_sendmsg_acl(const
906   *   *
907   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
908   */   */
909  int ccs_check_network_recvmsg_acl(const _Bool is_ipv6, const int sock_type,  static inline int ccs_check_network_recvmsg_acl(const bool is_ipv6,
910                                    const u8 *address, const u16 port)                                                  const int sock_type,
911                                                    const u8 *address,
912                                                    const u16 port)
913  {  {
914          int retval;          int retval;
915          const u8 operation          const u8 operation
# Line 898  int ccs_check_network_recvmsg_acl(const Line 921  int ccs_check_network_recvmsg_acl(const
921          current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
922          return retval;          return retval;
923  }  }
924    
925    #define MAX_SOCK_ADDR 128 /* net/socket.c */
926    
927    /* Check permission for creating a socket. */
928    int ccs_socket_create_permission(int family, int type, int protocol)
929    {
930            int error = 0;
931            /* Nothing to do if I am a kernel service. */
932            if (segment_eq(get_fs(), KERNEL_DS))
933                    return 0;
934            if (family == PF_PACKET && !ccs_capable(TOMOYO_USE_PACKET_SOCKET))
935                    return -EPERM;
936            if (family == PF_ROUTE && !ccs_capable(TOMOYO_USE_ROUTE_SOCKET))
937                    return -EPERM;
938            if (family != PF_INET && family != PF_INET6)
939                    return 0;
940            switch (type) {
941            case SOCK_STREAM:
942                    if (!ccs_capable(TOMOYO_INET_STREAM_SOCKET_CREATE))
943                            error = -EPERM;
944                    break;
945            case SOCK_DGRAM:
946                    if (!ccs_capable(TOMOYO_USE_INET_DGRAM_SOCKET))
947                            error = -EPERM;
948                    break;
949            case SOCK_RAW:
950                    if (!ccs_capable(TOMOYO_USE_INET_RAW_SOCKET))
951                            error = -EPERM;
952                    break;
953            }
954            return error;
955    }
956    
957    /* Check permission for listening a TCP socket. */
958    int ccs_socket_listen_permission(struct socket *sock)
959    {
960            int error = 0;
961            char addr[MAX_SOCK_ADDR];
962            int addr_len;
963            /* Nothing to do if I am a kernel service. */
964            if (segment_eq(get_fs(), KERNEL_DS))
965                    return 0;
966            if (sock->type != SOCK_STREAM)
967                    return 0;
968            switch (sock->sk->sk_family) {
969            case PF_INET:
970            case PF_INET6:
971                    break;
972            default:
973                    return 0;
974            }
975            if (!ccs_capable(TOMOYO_INET_STREAM_SOCKET_LISTEN))
976                    return -EPERM;
977            if (sock->ops->getname(sock, (struct sockaddr *) addr, &addr_len, 0))
978                    return -EPERM;
979            switch (((struct sockaddr *) addr)->sa_family) {
980                    struct sockaddr_in6 *addr6;
981                    struct sockaddr_in *addr4;
982            case AF_INET6:
983                    addr6 = (struct sockaddr_in6 *) addr;
984                    error = ccs_check_network_listen_acl(true,
985                                                         addr6->sin6_addr.s6_addr,
986                                                         addr6->sin6_port);
987                    break;
988            case AF_INET:
989                    addr4 = (struct sockaddr_in *) addr;
990                    error = ccs_check_network_listen_acl(false,
991                                                         (u8 *) &addr4->sin_addr,
992                                                         addr4->sin_port);
993                    break;
994            }
995            return error;
996    }
997    
998    /* Check permission for setting the remote IP address/port pair of a socket. */
999    int ccs_socket_connect_permission(struct socket *sock, struct sockaddr *addr,
1000                                      int addr_len)
1001    {
1002            int error = 0;
1003            const unsigned int type = sock->type;
1004            /* Nothing to do if I am a kernel service. */
1005            if (segment_eq(get_fs(), KERNEL_DS))
1006                    return 0;
1007            switch (type) {
1008            case SOCK_STREAM:
1009            case SOCK_DGRAM:
1010            case SOCK_RAW:
1011                    break;
1012            default:
1013                    return 0;
1014            }
1015            switch (addr->sa_family) {
1016                    struct sockaddr_in6 *addr6;
1017                    struct sockaddr_in *addr4;
1018                    u16 port;
1019            case AF_INET6:
1020                    if (addr_len < SIN6_LEN_RFC2133)
1021                            break;
1022                    addr6 = (struct sockaddr_in6 *) addr;
1023                    if (type != SOCK_RAW)
1024                            port = addr6->sin6_port;
1025                    else
1026                            port = htons(sock->sk->sk_protocol);
1027                    error = ccs_check_network_connect_acl(true, type,
1028                                                          addr6->sin6_addr.s6_addr,
1029                                                          port);
1030                    break;
1031            case AF_INET:
1032                    if (addr_len < sizeof(struct sockaddr_in))
1033                            break;
1034                    addr4 = (struct sockaddr_in *) addr;
1035                    if (type != SOCK_RAW)
1036                            port = addr4->sin_port;
1037                    else
1038                            port = htons(sock->sk->sk_protocol);
1039                    error = ccs_check_network_connect_acl(false, type,
1040                                                          (u8 *) &addr4->sin_addr,
1041                                                          port);
1042                    break;
1043            }
1044            if (type != SOCK_STREAM)
1045                    return error;
1046            switch (sock->sk->sk_family) {
1047            case PF_INET:
1048            case PF_INET6:
1049                    if (!ccs_capable(TOMOYO_INET_STREAM_SOCKET_CONNECT))
1050                            error = -EPERM;
1051                    break;
1052            }
1053            return error;
1054    }
1055    
1056    /* Check permission for setting the local IP address/port pair of a socket. */
1057    int ccs_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
1058                                   int addr_len)
1059    {
1060            int error = 0;
1061            const unsigned int type = sock->type;
1062            /* Nothing to do if I am a kernel service. */
1063            if (segment_eq(get_fs(), KERNEL_DS))
1064                    return 0;
1065            switch (type) {
1066            case SOCK_STREAM:
1067            case SOCK_DGRAM:
1068            case SOCK_RAW:
1069                    break;
1070            default:
1071                    return 0;
1072            }
1073            switch (addr->sa_family) {
1074                    struct sockaddr_in6 *addr6;
1075                    struct sockaddr_in *addr4;
1076                    u16 port;
1077            case AF_INET6:
1078                    if (addr_len < SIN6_LEN_RFC2133)
1079                            break;
1080                    addr6 = (struct sockaddr_in6 *) addr;
1081                    if (type != SOCK_RAW)
1082                            port = addr6->sin6_port;
1083                    else
1084                            port = htons(sock->sk->sk_protocol);
1085                    error = ccs_check_network_bind_acl(true, type,
1086                                                       addr6->sin6_addr.s6_addr,
1087                                                       port);
1088                    break;
1089            case AF_INET:
1090                    if (addr_len < sizeof(struct sockaddr_in))
1091                            break;
1092                    addr4 = (struct sockaddr_in *) addr;
1093                    if (type != SOCK_RAW)
1094                            port = addr4->sin_port;
1095                    else
1096                            port = htons(sock->sk->sk_protocol);
1097                    error = ccs_check_network_bind_acl(false, type,
1098                                                       (u8 *) &addr4->sin_addr,
1099                                                       port);
1100                    break;
1101            }
1102            return error;
1103    }
1104    
1105    /*
1106     * Check permission for accepting a TCP socket.
1107     *
1108     * Currently, the LSM hook for this purpose is not provided.
1109     */
1110    int ccs_socket_accept_permission(struct socket *sock, struct sockaddr *addr)
1111    {
1112            int error = 0;
1113            int addr_len;
1114            /* Nothing to do if I am a kernel service. */
1115            if (segment_eq(get_fs(), KERNEL_DS))
1116                    return 0;
1117            switch (sock->sk->sk_family) {
1118            case PF_INET:
1119            case PF_INET6:
1120                    break;
1121            default:
1122                    return 0;
1123            }
1124            error = sock->ops->getname(sock, addr, &addr_len, 2);
1125            if (error)
1126                    return error;
1127            switch (addr->sa_family) {
1128                    struct sockaddr_in6 *addr6;
1129                    struct sockaddr_in *addr4;
1130            case AF_INET6:
1131                    addr6 = (struct sockaddr_in6 *) addr;
1132                    error = ccs_check_network_accept_acl(true,
1133                                                         addr6->sin6_addr.s6_addr,
1134                                                         addr6->sin6_port);
1135                    break;
1136            case AF_INET:
1137                    addr4 = (struct sockaddr_in *) addr;
1138                    error = ccs_check_network_accept_acl(false,
1139                                                         (u8 *) &addr4->sin_addr,
1140                                                         addr4->sin_port);
1141                    break;
1142            }
1143            return error;
1144    }
1145    
1146    /* Check permission for sending a datagram via a UDP or RAW socket. */
1147    int ccs_socket_sendmsg_permission(struct socket *sock, struct sockaddr *addr,
1148                                      int addr_len)
1149    {
1150            int error = 0;
1151            const int type = sock->type;
1152            /* Nothing to do if I am a kernel service. */
1153            if (segment_eq(get_fs(), KERNEL_DS))
1154                    return 0;
1155            if (!addr || (type != SOCK_DGRAM && type != SOCK_RAW))
1156                    return 0;
1157            switch (addr->sa_family) {
1158                    struct sockaddr_in6 *addr6;
1159                    struct sockaddr_in *addr4;
1160                    u16 port;
1161            case AF_INET6:
1162                    if (addr_len < SIN6_LEN_RFC2133)
1163                            break;
1164                    addr6 = (struct sockaddr_in6 *) addr;
1165                    if (type == SOCK_DGRAM)
1166                            port = addr6->sin6_port;
1167                    else
1168                            port = htons(sock->sk->sk_protocol);
1169                    error = ccs_check_network_sendmsg_acl(true, type,
1170                                                          addr6->sin6_addr.s6_addr,
1171                                                          port);
1172                    break;
1173            case AF_INET:
1174                    if (addr_len < sizeof(struct sockaddr_in))
1175                            break;
1176                    addr4 = (struct sockaddr_in *) addr;
1177                    if (type == SOCK_DGRAM)
1178                            port = addr4->sin_port;
1179                    else
1180                            port = htons(sock->sk->sk_protocol);
1181                    error = ccs_check_network_sendmsg_acl(false, type,
1182                                                          (u8 *) &addr4->sin_addr,
1183                                                          port);
1184                    break;
1185            }
1186            return error;
1187    }
1188    
1189    #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
1190    #if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5
1191    
1192    static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
1193    {
1194            return skb->nh.iph;
1195    }
1196    
1197    static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
1198    {
1199            return skb->h.uh;
1200    }
1201    
1202    static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
1203    {
1204            return skb->nh.ipv6h;
1205    }
1206    
1207    #endif
1208    #endif
1209    
1210    /*
1211     * Check permission for receiving a datagram via a UDP or RAW socket.
1212     *
1213     * Currently, the LSM hook for this purpose is not provided.
1214     */
1215    int ccs_socket_recv_datagram_permission(struct sock *sk, struct sk_buff *skb,
1216                                            const unsigned int flags)
1217    {
1218            int error = 0;
1219            const unsigned int type = sk->sk_type;
1220            /* Nothing to do if I didn't receive a datagram. */
1221            if (!skb)
1222                    return 0;
1223            /* Nothing to do if I can't sleep. */
1224    #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
1225            if (in_interrupt())
1226                    return 0;
1227    #else
1228            if (in_atomic())
1229                    return 0;
1230    #endif
1231            /* Nothing to do if I am a kernel service. */
1232            if (segment_eq(get_fs(), KERNEL_DS))
1233                    return 0;
1234            if (type != SOCK_DGRAM && type != SOCK_RAW)
1235                    return 0;
1236    
1237            switch (sk->sk_family) {
1238                    struct in6_addr sin6;
1239                    struct in_addr sin4;
1240                    u16 port;
1241            case PF_INET6:
1242                    if (type == SOCK_DGRAM) { /* UDP IPv6 */
1243                            if (skb->protocol == htons(ETH_P_IP)) {
1244                                    ipv6_addr_set(&sin6, 0, 0, htonl(0xffff),
1245                                                  ip_hdr(skb)->saddr);
1246                            } else {
1247                                    ipv6_addr_copy(&sin6, &ipv6_hdr(skb)->saddr);
1248                            }
1249                            port = udp_hdr(skb)->source;
1250                    } else { /* RAW IPv6 */
1251                            ipv6_addr_copy(&sin6, &ipv6_hdr(skb)->saddr);
1252                            port = htons(sk->sk_protocol);
1253                    }
1254                    error = ccs_check_network_recvmsg_acl(true, type,
1255                                                          (u8 *) &sin6, port);
1256                    break;
1257            case PF_INET:
1258                    if (type == SOCK_DGRAM) { /* UDP IPv4 */
1259                            sin4.s_addr = ip_hdr(skb)->saddr;
1260                            port = udp_hdr(skb)->source;
1261                    } else { /* RAW IPv4 */
1262                            sin4.s_addr = ip_hdr(skb)->saddr;
1263                            port = htons(sk->sk_protocol);
1264                    }
1265                    error = ccs_check_network_recvmsg_acl(false, type,
1266                                                          (u8 *) &sin4, port);
1267                    break;
1268            }
1269            if (!error)
1270                    return 0;
1271    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1272            lock_sock(sk);
1273    #endif
1274            /*
1275             * Remove from queue if MSG_PEEK is used so that
1276             * the head message from unwanted source in receive queue will not
1277             * prevent the caller from picking up next message from wanted source
1278             * when the caller is using MSG_PEEK flag for picking up.
1279             */
1280            if (flags & MSG_PEEK) {
1281                    unsigned long cpu_flags;
1282                    /***** CRITICAL SECTION START *****/
1283                    spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags);
1284                    if (skb == skb_peek(&sk->sk_receive_queue)) {
1285                            __skb_unlink(skb, &sk->sk_receive_queue);
1286                            atomic_dec(&skb->users);
1287                    }
1288                    spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags);
1289                    /***** CRITICAL SECTION END *****/
1290            }
1291            /* Drop reference count. */
1292            skb_free_datagram(sk, skb);
1293    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1294            release_sock(sk);
1295    #endif
1296            /* Hope less harmful than -EPERM. */
1297            return -EAGAIN;
1298    }

Legend:
Removed from v.2030  
changed lines
  Added in v.2037

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26