Commit 82f1671a authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/davem/sparc-2.6

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents 2b308273 0ef8ced2
......@@ -316,6 +316,30 @@ tcp_vegas_cong_avoid - BOOLEAN
not as aggressive as TCP Reno.
Default:0
tcp_bic - BOOLEAN
Enable BIC TCP congestion control algorithm.
BIC-TCP is a sender-side only change that ensures a linear RTT
fairness under large windows while offering both scalability and
bounded TCP-friendliness. The protocol combines two schemes
called additive increase and binary search increase. When the
congestion window is large, additive increase with a large
increment ensures linear RTT fairness as well as good
scalability. Under small congestion windows, binary search
increase provides TCP friendliness.
Default: 0
tcp_bic_low_window - INTEGER
Sets the threshold window (in packets) where BIC TCP starts to
adjust the congestion window. Below this threshold BIC TCP behaves
the same as the default TCP Reno.
Default: 14
tcp_bic_fast_convergence - BOOLEAN
Forces BIC TCP to more quickly respond to changes in congestion
window. Allows two flows sharing the same connection to converge
more rapidly.
Default: 1
ip_local_port_range - 2 INTEGERS
Defines the local port range that is used by TCP and UDP to
choose the local port. The first number is the first, the
......
......@@ -56,12 +56,12 @@ static int chksum_setkey(void *ctx, const u8 *key, unsigned int keylen,
return 0;
}
static void chksum_update(void *ctx, const u8 *data, size_t length)
static void chksum_update(void *ctx, const u8 *data, unsigned int length)
{
struct chksum_ctx *mctx = ctx;
u32 mcrc;
mcrc = crc32c(mctx->crc, data, length);
mcrc = crc32c(mctx->crc, data, (size_t)length);
mctx->crc = mcrc;
}
......
......@@ -900,7 +900,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
unsigned short int orig_port = 0;
if(*csocket == NULL) {
rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
if (rc < 0) {
cERROR(1, ("Error %d creating socket",rc));
*csocket = NULL;
......@@ -1007,7 +1007,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
int connected = 0;
if(*csocket == NULL) {
rc = sock_create(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
if (rc < 0) {
cERROR(1, ("Error %d creating ipv6 socket",rc));
*csocket = NULL;
......
......@@ -149,6 +149,10 @@ extern int sock_unregister(int family);
extern struct socket *sock_alloc(void);
extern int sock_create(int family, int type, int proto,
struct socket **res);
extern int sock_create_kern(int family, int type, int proto,
struct socket **res);
extern int sock_create_lite(int family, int type, int proto,
struct socket **res);
extern void sock_release(struct socket *sock);
extern int sock_sendmsg(struct socket *sock, struct msghdr *msg,
size_t len);
......
......@@ -680,6 +680,7 @@ struct swap_info_struct;
* @family contains the requested protocol family.
* @type contains the requested communications type.
* @protocol contains the requested protocol.
* @kern set to 1 if a kernel socket.
* Return 0 if permission is granted.
* @socket_post_create:
* This hook allows a module to update or allocate a per-socket security
......@@ -694,6 +695,7 @@ struct swap_info_struct;
* @family contains the requested protocol family.
* @type contains the requested communications type.
* @protocol contains the requested protocol.
* @kern set to 1 if a kernel socket.
* @socket_bind:
* Check permission before socket protocol layer bind operation is
* performed and the socket @sock is bound to the address specified in the
......@@ -1198,9 +1200,9 @@ struct security_operations {
struct socket * other, struct sock * newsk);
int (*unix_may_send) (struct socket * sock, struct socket * other);
int (*socket_create) (int family, int type, int protocol);
int (*socket_create) (int family, int type, int protocol, int kern);
void (*socket_post_create) (struct socket * sock, int family,
int type, int protocol);
int type, int protocol, int kern);
int (*socket_bind) (struct socket * sock,
struct sockaddr * address, int addrlen);
int (*socket_connect) (struct socket * sock,
......@@ -2526,17 +2528,19 @@ static inline int security_unix_may_send(struct socket * sock,
return security_ops->unix_may_send(sock, other);
}
static inline int security_socket_create (int family, int type, int protocol)
static inline int security_socket_create (int family, int type,
int protocol, int kern)
{
return security_ops->socket_create(family, type, protocol);
return security_ops->socket_create(family, type, protocol, kern);
}
static inline void security_socket_post_create(struct socket * sock,
int family,
int type,
int protocol)
int protocol, int kern)
{
security_ops->socket_post_create(sock, family, type, protocol);
security_ops->socket_post_create(sock, family, type,
protocol, kern);
}
static inline int security_socket_bind(struct socket * sock,
......@@ -2645,7 +2649,8 @@ static inline int security_unix_may_send(struct socket * sock,
return 0;
}
static inline int security_socket_create (int family, int type, int protocol)
static inline int security_socket_create (int family, int type,
int protocol, int kern)
{
return 0;
}
......@@ -2653,7 +2658,7 @@ static inline int security_socket_create (int family, int type, int protocol)
static inline void security_socket_post_create(struct socket * sock,
int family,
int type,
int protocol)
int protocol, int kern)
{
}
......
......@@ -332,6 +332,9 @@ enum
NET_TCP_VEGAS_ALPHA=99,
NET_TCP_VEGAS_BETA=100,
NET_TCP_VEGAS_GAMMA=101,
NET_TCP_BIC=102,
NET_TCP_BIC_FAST_CONVERGENCE=103,
NET_TCP_BIC_LOW_WINDOW=104,
};
enum {
......
......@@ -400,6 +400,13 @@ struct tcp_opt {
__u32 minRTT; /* min of RTTs measured within last RTT (in usec) */
__u32 baseRTT; /* the min of all Vegas RTT measurements seen (in usec) */
} vegas;
/* BI TCP Parameters */
struct {
__u32 cnt; /* increase cwnd by 1 after this number of ACKs */
__u32 last_max_cwnd; /* last maximium snd_cwnd */
__u32 last_cwnd; /* the last snd_cwnd */
} bictcp;
};
/* WARNING: don't change the layout of the members in tcp_sock! */
......
......@@ -509,6 +509,25 @@ static __inline__ int tcp_sk_listen_hashfn(struct sock *sk)
# define TCP_TW_RECYCLE_TICK (12+2-TCP_TW_RECYCLE_SLOTS_LOG)
#endif
#define BICTCP_1_OVER_BETA 8 /*
* Fast recovery
* multiplicative decrease factor
*/
#define BICTCP_MAX_INCREMENT 32 /*
* Limit on the amount of
* increment allowed during
* binary search.
*/
#define BICTCP_FUNC_OF_MIN_INCR 11 /*
* log(B/Smin)/log(B/(B-1))+1,
* Smin:min increment
* B:log factor
*/
#define BICTCP_B 4 /*
* In binary search,
* go to point (max+min)/N
*/
/*
* TCP option
*/
......@@ -588,6 +607,9 @@ extern int sysctl_tcp_vegas_alpha;
extern int sysctl_tcp_vegas_beta;
extern int sysctl_tcp_vegas_gamma;
extern int sysctl_tcp_nometrics_save;
extern int sysctl_tcp_bic;
extern int sysctl_tcp_bic_fast_convergence;
extern int sysctl_tcp_bic_low_window;
extern atomic_t tcp_memory_allocated;
extern atomic_t tcp_sockets_allocated;
......@@ -1207,11 +1229,30 @@ static __inline__ unsigned int tcp_packets_in_flight(struct tcp_opt *tp)
/* Recalculate snd_ssthresh, we want to set it to:
*
* Reno:
* one half the current congestion window, but no
* less than two segments
*
* BIC:
* behave like Reno until low_window is reached,
* then increase congestion window slowly
*/
static inline __u32 tcp_recalc_ssthresh(struct tcp_opt *tp)
{
if (sysctl_tcp_bic) {
if (sysctl_tcp_bic_fast_convergence &&
tp->snd_cwnd < tp->bictcp.last_max_cwnd)
tp->bictcp.last_max_cwnd
= (tp->snd_cwnd * (2*BICTCP_1_OVER_BETA-1))
/ (BICTCP_1_OVER_BETA/2);
else
tp->bictcp.last_max_cwnd = tp->snd_cwnd;
if (tp->snd_cwnd > sysctl_tcp_bic_low_window)
return max(tp->snd_cwnd - (tp->snd_cwnd/BICTCP_1_OVER_BETA),
2U);
}
return max(tp->snd_cwnd >> 1U, 2U);
}
......
......@@ -596,9 +596,15 @@ static int init(void * unused)
do_pre_smp_initcalls();
smp_init();
do_basic_setup();
/*
* Do this before initcalls, because some drivers want to access
* firmware files.
*/
populate_rootfs();
do_basic_setup();
/*
* check if there is an early userspace init. If yes, let it do all
* the work
......
......@@ -158,7 +158,8 @@ static int rfcomm_l2sock_create(struct socket **sock)
BT_DBG("");
err = sock_create(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP, sock);
err = sock_create_kern(PF_BLUETOOTH, SOCK_SEQPACKET,
BTPROTO_L2CAP, sock);
if (!err) {
struct sock *sk = (*sock)->sk;
sk->sk_data_ready = rfcomm_l2data_ready;
......@@ -1641,11 +1642,9 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s)
BT_DBG("session %p", s);
nsock = sock_alloc();
if (!nsock)
if (sock_create_lite(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP, &nsock))
return;
nsock->type = sock->type;
nsock->ops = sock->ops;
__module_get(nsock->ops->owner);
......
......@@ -976,7 +976,7 @@ static int __init aun_udp_initialise(void)
/* We can count ourselves lucky Acorn machines are too dim to
speak IPv6. :-) */
if ((error = sock_create(PF_INET, SOCK_DGRAM, 0, &udpsock)) < 0)
if ((error = sock_create_kern(PF_INET, SOCK_DGRAM, 0, &udpsock)) < 0)
{
printk("AUN: socket error %d\n", -error);
return error;
......
......@@ -891,15 +891,14 @@ int arp_process(struct sk_buff *skb)
if (n) {
int state = NUD_REACHABLE;
int override = 0;
int override;
/* If several different ARP replies follows back-to-back,
use the FIRST one. It is possible, if several proxy
agents are active. Taking the first reply prevents
arp trashing and chooses the fastest router.
*/
if (jiffies - n->updated >= n->parms->locktime)
override = 1;
override = time_after(jiffies, n->updated + n->parms->locktime);
/* Broadcast replies and request packets
do not assert neighbour reachability.
......
......@@ -1108,8 +1108,8 @@ void __init icmp_init(struct net_proto_family *ops)
if (!cpu_possible(i))
continue;
err = sock_create(PF_INET, SOCK_RAW, IPPROTO_ICMP,
&per_cpu(__icmp_socket, i));
err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP,
&per_cpu(__icmp_socket, i));
if (err < 0)
panic("Failed to create the ICMP control socket.\n");
......
......@@ -480,7 +480,7 @@ static struct socket * make_send_sock(void)
struct socket *sock;
/* First create a socket */
if (sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock) < 0) {
if (sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock) < 0) {
IP_VS_ERR("Error during creation of socket; terminating\n");
return NULL;
}
......@@ -521,7 +521,7 @@ static struct socket * make_receive_sock(void)
struct socket *sock;
/* First create a socket */
if (sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock) < 0) {
if (sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock) < 0) {
IP_VS_ERR("Error during creation of socket; terminating\n");
return NULL;
}
......
......@@ -641,6 +641,30 @@ ctl_table ipv4_table[] = {
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_TCP_BIC,
.procname = "tcp_bic",
.data = &sysctl_tcp_bic,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_TCP_BIC_FAST_CONVERGENCE,
.procname = "tcp_bic_fast_convergence",
.data = &sysctl_tcp_bic_fast_convergence,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{
.ctl_name = NET_TCP_BIC_LOW_WINDOW,
.procname = "tcp_bic_low_window",
.data = &sysctl_tcp_bic_low_window,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{ .ctl_name = 0 }
};
......
......@@ -97,6 +97,9 @@ int sysctl_tcp_vegas_cong_avoid;
int sysctl_tcp_vegas_alpha = 1<<V_PARAM_SHIFT;
int sysctl_tcp_vegas_beta = 3<<V_PARAM_SHIFT;
int sysctl_tcp_vegas_gamma = 1<<V_PARAM_SHIFT;
int sysctl_tcp_bic;
int sysctl_tcp_bic_fast_convergence = 1;
int sysctl_tcp_bic_low_window = 14;
#define FLAG_DATA 0x01 /* Incoming frame contained data. */
#define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */
......@@ -1858,6 +1861,68 @@ tcp_ack_update_rtt(struct tcp_opt *tp, int flag, s32 seq_rtt)
else if (seq_rtt >= 0)
tcp_ack_no_tstamp(tp, seq_rtt, flag);
}
/*
* Compute congestion window to use.
*
* This is from the implementation of BICTCP in
* Lison-Xu, Kahaled Harfoush, and Injog Rhee.
* "Binary Increase Congestion Control for Fast, Long Distance
* Networks" in InfoComm 2004
* Available from:
* http://www.csc.ncsu.edu/faculty/rhee/export/bitcp.pdf
*
* Unless BIC is enabled and congestion window is large
* this behaves the same as the original Reno.
*/
static inline __u32 bictcp_cwnd(struct tcp_opt *tp)
{
/* orignal Reno behaviour */
if (!sysctl_tcp_bic)
return tp->snd_cwnd;
if (tp->bictcp.last_cwnd == tp->snd_cwnd)
return tp->bictcp.cnt; /* same cwnd, no update */
tp->bictcp.last_cwnd = tp->snd_cwnd;
/* start off normal */
if (tp->snd_cwnd <= sysctl_tcp_bic_low_window)
tp->bictcp.cnt = tp->snd_cwnd;
/* binary increase */
else if (tp->snd_cwnd < tp->bictcp.last_max_cwnd) {
__u32 dist = (tp->bictcp.last_max_cwnd - tp->snd_cwnd)
/ BICTCP_B;
if (dist > BICTCP_MAX_INCREMENT)
/* linear increase */
tp->bictcp.cnt = tp->snd_cwnd / BICTCP_MAX_INCREMENT;
else if (dist <= 1U)
/* binary search increase */
tp->bictcp.cnt = tp->snd_cwnd * BICTCP_FUNC_OF_MIN_INCR
/ BICTCP_B;
else
/* binary search increase */
tp->bictcp.cnt = tp->snd_cwnd / dist;
} else {
/* slow start amd linear increase */
if (tp->snd_cwnd < tp->bictcp.last_max_cwnd + BICTCP_B)
/* slow start */
tp->bictcp.cnt = tp->snd_cwnd * BICTCP_FUNC_OF_MIN_INCR
/ BICTCP_B;
else if (tp->snd_cwnd < tp->bictcp.last_max_cwnd
+ BICTCP_MAX_INCREMENT*(BICTCP_B-1))
/* slow start */
tp->bictcp.cnt = tp->snd_cwnd * (BICTCP_B-1)
/ (tp->snd_cwnd-tp->bictcp.last_max_cwnd);
else
/* linear increase */
tp->bictcp.cnt = tp->snd_cwnd / BICTCP_MAX_INCREMENT;
}
return tp->bictcp.cnt;
}
/* This is Jacobson's slow start and congestion avoidance.
* SIGCOMM '88, p. 328.
*/
......@@ -1871,7 +1936,7 @@ static __inline__ void reno_cong_avoid(struct tcp_opt *tp)
/* In dangerous area, increase slowly.
* In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd
*/
if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
if (tp->snd_cwnd_cnt >= bictcp_cwnd(tp)) {
if (tp->snd_cwnd < tp->snd_cwnd_clamp)
tp->snd_cwnd++;
tp->snd_cwnd_cnt=0;
......
......@@ -2609,7 +2609,7 @@ struct proto tcp_prot = {
void __init tcp_v4_init(struct net_proto_family *ops)
{
int err = sock_create(PF_INET, SOCK_RAW, IPPROTO_TCP, &tcp_socket);
int err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_TCP, &tcp_socket);
if (err < 0)
panic("Failed to create the TCP control socket.\n");
tcp_socket->sk->sk_allocation = GFP_ATOMIC;
......
......@@ -766,6 +766,9 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
newtp->snd_cwnd = 2;
newtp->snd_cwnd_cnt = 0;
newtp->bictcp.cnt = 0;
newtp->bictcp.last_max_cwnd = newtp->bictcp.last_cwnd = 0;
newtp->frto_counter = 0;
newtp->frto_highmark = 0;
......
......@@ -682,8 +682,8 @@ int __init icmpv6_init(struct net_proto_family *ops)
if (!cpu_possible(i))
continue;
err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
&per_cpu(__icmpv6_socket, i));
err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
&per_cpu(__icmpv6_socket, i));
if (err < 0) {
printk(KERN_ERR
"Failed to initialize the ICMP6 control socket "
......
......@@ -2452,7 +2452,7 @@ int __init igmp6_init(struct net_proto_family *ops)
struct sock *sk;
int err;
err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &igmp6_socket);
err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &igmp6_socket);
if (err < 0) {
printk(KERN_ERR
"Failed to initialize the IGMP6 control socket (err %d).\n",
......
......@@ -1443,7 +1443,7 @@ int __init ndisc_init(struct net_proto_family *ops)
struct sock *sk;
int err;
err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket);
err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket);
if (err < 0) {
ND_PRINTK0(KERN_ERR
"ICMPv6 NDISC: Failed to initialize the control socket (err %d).\n",
......
......@@ -833,11 +833,9 @@ netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len))
if (unit<0 || unit>=MAX_LINKS)
return NULL;
if (!(sock = sock_alloc()))
if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock))
return NULL;
sock->type = SOCK_RAW;
if (netlink_create(sock, unit) < 0) {
sock_release(sock);
return NULL;
......
......@@ -112,7 +112,7 @@ static int netlink_open(struct inode * inode, struct file * file)
if (test_and_set_bit(minor, &open_map))
return -EBUSY;
err = sock_create(PF_NETLINK, SOCK_RAW, minor, &sock);
err = sock_create_kern(PF_NETLINK, SOCK_RAW, minor, &sock);
if (err < 0)
goto out;
......
......@@ -86,7 +86,7 @@ int rxrpc_create_transport(unsigned short port,
trans->port = port;
/* create a UDP socket to be my actual transport endpoint */
ret = sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &trans->socket);
ret = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &trans->socket);
if (ret < 0)
goto error;
......
......@@ -1195,7 +1195,7 @@ int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *asoc,
{
int var_size2 = ntohs(cookie->peer_init->chunk_hdr.length);
int var_size3 = cookie->raw_addr_list_len;
__u8 *raw = (__u8 *)cookie + sizeof(struct sctp_cookie) + var_size2;
__u8 *raw = (__u8 *)cookie->peer_init + var_size2;
return sctp_raw_to_bind_addrs(&asoc->base.bind_addr, raw, var_size3,
asoc->ep->base.bind_addr.port, gfp);
......
......@@ -1056,8 +1056,10 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
}
/* Get the highest TSN in the sack. */
highest_tsn = sack_ctsn +
ntohs(frags[ntohs(sack->num_gap_ack_blocks) - 1].gab.end);
highest_tsn = sack_ctsn;
if (sack->num_gap_ack_blocks)
highest_tsn +=
ntohs(frags[ntohs(sack->num_gap_ack_blocks) - 1].gab.end);
if (TSN_lt(asoc->highest_sacked, highest_tsn)) {
highest_new_tsn = highest_tsn;
......
......@@ -653,8 +653,8 @@ int sctp_ctl_sock_init(void)
else
family = PF_INET;
err = sock_create(family, SOCK_SEQPACKET, IPPROTO_SCTP,
&sctp_ctl_socket);
err = sock_create_kern(family, SOCK_SEQPACKET, IPPROTO_SCTP,
&sctp_ctl_socket);
if (err < 0) {
printk(KERN_ERR
"SCTP: Failed to create the SCTP control socket.\n");
......
......@@ -77,7 +77,7 @@ struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, int gfp)
/* Initialize an ULP event from an given skb. */
void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags)
{
memset(event, sizeof(struct sctp_ulpevent), 0x00);
memset(event, 0, sizeof(struct sctp_ulpevent));
event->msg_flags = msg_flags;
}
......
......@@ -79,7 +79,7 @@ struct sctp_ulpq *sctp_ulpq_new(struct sctp_association *asoc, int gfp)
struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *ulpq,
struct sctp_association *asoc)
{
memset(ulpq, sizeof(struct sctp_ulpq), 0x00);
memset(ulpq, 0, sizeof(struct sctp_ulpq));
ulpq->asoc = asoc;
skb_queue_head_init(&ulpq->reasm);
......
......@@ -840,6 +840,27 @@ static int sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return err;
}
int sock_create_lite(int family, int type, int protocol, struct socket **res)
{
int err;
struct socket *sock = NULL;
err = security_socket_create(family, type, protocol, 1);
if (err)
goto out;
sock = sock_alloc();
if (!sock) {
err = -ENOMEM;
goto out;
}
security_socket_post_create(sock, family, type, protocol, 1);
sock->type = type;
out:
*res = sock;
return err;
}
/* No kernel lock held - perfect */
static unsigned int sock_poll(struct file *file, poll_table * wait)
......@@ -983,8 +1004,7 @@ int sock_wake_async(struct socket *sock, int how, int band)
return 0;
}
int sock_create(int family, int type, int protocol, struct socket **res)
static int __sock_create(int family, int type, int protocol, struct socket **res, int kern)
{
int i;
int err;
......@@ -1012,7 +1032,7 @@ int sock_create(int family, int type, int protocol, struct socket **res)
family = PF_PACKET;
}
err = security_socket_create(family, type, protocol);
err = security_socket_create(family, type, protocol, kern);
if (err)
return err;
......@@ -1075,7 +1095,7 @@ int sock_create(int family, int type, int protocol, struct socket **res)
*/
module_put(net_families[family]->owner);
*res = sock;
security_socket_post_create(sock, family, type, protocol);
security_socket_post_create(sock, family, type, protocol, kern);
out:
net_family_read_unlock();
......@@ -1087,6 +1107,16 @@ int sock_create(int family, int type, int protocol, struct socket **res)
goto out;
}
int sock_create(int family, int type, int protocol, struct socket **res)
{
return __sock_create(family, type, protocol, res, 0);
}
int sock_create_kern(int family, int type, int protocol, struct socket **res)
{
return __sock_create(family, type, protocol, res, 1);
}
asmlinkage long sys_socket(int family, int type, int protocol)
{
int retval;
......@@ -1991,6 +2021,8 @@ EXPORT_SYMBOL(move_addr_to_user);
EXPORT_SYMBOL(sock_alloc);
EXPORT_SYMBOL(sock_alloc_inode);
EXPORT_SYMBOL(sock_create);
EXPORT_SYMBOL(sock_create_kern);
EXPORT_SYMBOL(sock_create_lite);
EXPORT_SYMBOL(sock_map_fd);
EXPORT_SYMBOL(sock_recvmsg);
EXPORT_SYMBOL(sock_register);
......
......@@ -781,13 +781,15 @@ svc_tcp_accept(struct svc_sock *svsk)
if (!sock)
return;
if (!(newsock = sock_alloc())) {
printk(KERN_WARNING "%s: no more sockets!\n", serv->sv_name);
err = sock_create_lite(PF_INET, SOCK_STREAM, IPPROTO_TCP, &newsock);
if (err) {
if (err == -ENOMEM)
printk(KERN_WARNING "%s: no more sockets!\n",
serv->sv_name);
return;
}
dprintk("svc: tcp_accept %p allocated\n", newsock);
newsock->type = sock->type;
dprintk("svc: tcp_accept %p allocated\n", newsock);
newsock->ops = ops = sock->ops;
clear_bit(SK_CONN, &svsk->sk_flags);
......@@ -1413,7 +1415,7 @@ svc_create_socket(struct svc_serv *serv, int protocol, struct sockaddr_in *sin)
}
type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
if ((error = sock_create(PF_INET, type, protocol, &sock)) < 0)
if ((error = sock_create_kern(PF_INET, type, protocol, &sock)) < 0)
return error;
if (sin != NULL) {
......
......@@ -1567,7 +1567,7 @@ static struct socket * xprt_create_socket(struct rpc_xprt *xprt, int proto, int
type = (proto == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
if ((err = sock_create(PF_INET, type, proto, &sock)) < 0) {
if ((err = sock_create_kern(PF_INET, type, proto, &sock)) < 0) {
printk("RPC: can't create socket (%d).\n", -err);
return NULL;
}
......
......@@ -750,13 +750,14 @@ static int dummy_unix_may_send (struct socket *sock,
return 0;
}
static int dummy_socket_create (int family, int type, int protocol)
static int dummy_socket_create (int family, int type,
int protocol, int kern)
{
return 0;
}
static void dummy_socket_post_create (struct socket *sock, int family, int type,
int protocol)
int protocol, int kern)
{
return;
}
......
......@@ -2810,34 +2810,43 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock,
struct inode_security_struct *isec;
struct task_security_struct *tsec;
struct avc_audit_data ad;
int err;
int err = 0;
tsec = task->security;
isec = SOCK_INODE(sock)->i_security;
if (isec->sid == SECINITSID_KERNEL)
goto out;
AVC_AUDIT_DATA_INIT(&ad,NET);
ad.u.net.sk = sock->sk;
err = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
perms, &isec->avcr, &ad);
out:
return err;
}
static int selinux_socket_create(int family, int type, int protocol)
static int selinux_socket_create(int family, int type,
int protocol, int kern)
{
int err;
int err = 0;
struct task_security_struct *tsec;
tsec = current->security;
if (kern)
goto out;
tsec = current->security;
err = avc_has_perm(tsec->sid, tsec->sid,
socket_type_to_security_class(family, type),
SOCKET__CREATE, NULL, NULL);
out:
return err;
}
static void selinux_socket_post_create(struct socket *sock, int family, int type, int protocol)
static void selinux_socket_post_create(struct socket *sock, int family,
int type, int protocol, int kern)
{
int err;
struct inode_security_struct *isec;
......@@ -2850,7 +2859,7 @@ static void selinux_socket_post_create(struct socket *sock, int family, int type
tsec = current->security;
isec->sclass = socket_type_to_security_class(family, type);
isec->sid = tsec->sid;
isec->sid = kern ? SECINITSID_KERNEL : tsec->sid;
return;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment