Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
b884a92a
Commit
b884a92a
authored
Nov 23, 2007
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Import 2.1.91pre2
parent
f26125cb
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
214 additions
and
257 deletions
+214
-257
Makefile
Makefile
+1
-1
arch/i386/kernel/process.c
arch/i386/kernel/process.c
+2
-0
fs/buffer.c
fs/buffer.c
+12
-11
include/linux/swap.h
include/linux/swap.h
+0
-1
kernel/sysctl.c
kernel/sysctl.c
+1
-1
mm/filemap.c
mm/filemap.c
+4
-0
mm/page_alloc.c
mm/page_alloc.c
+3
-1
mm/swap.c
mm/swap.c
+3
-3
mm/vmscan.c
mm/vmscan.c
+28
-18
net/core/datagram.c
net/core/datagram.c
+10
-19
net/core/iovec.c
net/core/iovec.c
+24
-67
net/packet/af_packet.c
net/packet/af_packet.c
+79
-93
net/socket.c
net/socket.c
+14
-14
net/unix/af_unix.c
net/unix/af_unix.c
+33
-28
No files found.
Makefile
View file @
b884a92a
...
@@ -242,7 +242,7 @@ newversion:
...
@@ -242,7 +242,7 @@ newversion:
include/linux/compile.h
:
$(CONFIGURATION) include/linux/version.h newversion
include/linux/compile.h
:
$(CONFIGURATION) include/linux/version.h newversion
@
echo
-n
\#
define UTS_VERSION
\"\#
`
cat
.version
`
>
.ver
@
echo
-n
\#
define UTS_VERSION
\"\#
`
cat
.version
`
>
.ver
@
if
[
-
z
"
$(SMP)
"
]
;
then
echo
-n
" SMP"
>>
.ver
;
fi
@
if
[
-
n
"
$(SMP)
"
]
;
then
echo
-n
" SMP"
>>
.ver
;
fi
@
if
[
-f
.name
]
;
then
echo
-n
\-
`
cat
.name
`
>>
.ver
;
fi
@
if
[
-f
.name
]
;
then
echo
-n
\-
`
cat
.name
`
>>
.ver
;
fi
@
echo
' '
`
date
`
'"'
>>
.ver
@
echo
' '
`
date
`
'"'
>>
.ver
@
echo
\#
define LINUX_COMPILE_TIME
\"
`
date
+%T
`
\"
>>
.ver
@
echo
\#
define LINUX_COMPILE_TIME
\"
`
date
+%T
`
\"
>>
.ver
...
...
arch/i386/kernel/process.c
View file @
b884a92a
...
@@ -171,6 +171,8 @@ int cpu_idle(void *unused)
...
@@ -171,6 +171,8 @@ int cpu_idle(void *unused)
asmlinkage
int
sys_idle
(
void
)
asmlinkage
int
sys_idle
(
void
)
{
{
if
(
current
->
pid
!=
0
)
return
-
EPERM
;
cpu_idle
(
NULL
);
cpu_idle
(
NULL
);
return
0
;
return
0
;
}
}
...
...
fs/buffer.c
View file @
b884a92a
...
@@ -55,12 +55,9 @@ static char buffersize_index[17] =
...
@@ -55,12 +55,9 @@ static char buffersize_index[17] =
number of unused buffer heads */
number of unused buffer heads */
/*
/*
* H
ow large a hash table do we need?
* H
ash table mask..
*/
*/
#define HASH_PAGES_ORDER 4
static
unsigned
long
bh_hash_mask
=
0
;
#define HASH_PAGES (1UL << HASH_PAGES_ORDER)
#define NR_HASH (HASH_PAGES*PAGE_SIZE/sizeof(struct buffer_head *))
#define HASH_MASK (NR_HASH-1)
static
int
grow_buffers
(
int
pri
,
int
size
);
static
int
grow_buffers
(
int
pri
,
int
size
);
...
@@ -421,7 +418,7 @@ void invalidate_buffers(kdev_t dev)
...
@@ -421,7 +418,7 @@ void invalidate_buffers(kdev_t dev)
}
}
}
}
#define _hashfn(dev,block) (((unsigned)(HASHDEV(dev)^block))
&HASH_MASK
)
#define _hashfn(dev,block) (((unsigned)(HASHDEV(dev)^block))
& bh_hash_mask
)
#define hash(dev,block) hash_table[_hashfn(dev,block)]
#define hash(dev,block) hash_table[_hashfn(dev,block)]
static
inline
void
remove_from_hash_queue
(
struct
buffer_head
*
bh
)
static
inline
void
remove_from_hash_queue
(
struct
buffer_head
*
bh
)
...
@@ -732,7 +729,7 @@ static void refill_freelist(int size)
...
@@ -732,7 +729,7 @@ static void refill_freelist(int size)
needed
=
bdf_prm
.
b_un
.
nrefill
*
size
;
needed
=
bdf_prm
.
b_un
.
nrefill
*
size
;
while
((
nr_free_pages
>
freepages
.
min
*
2
)
&&
while
((
nr_free_pages
>
freepages
.
min
*
2
)
&&
BUFFER_MEM
<
(
buffer_mem
.
max_percent
*
num_physpages
/
100
)
&&
(
buffermem
>>
PAGE_SHIFT
)
*
100
<
(
buffer_mem
.
max_percent
*
num_physpages
)
&&
grow_buffers
(
GFP_BUFFER
,
size
))
{
grow_buffers
(
GFP_BUFFER
,
size
))
{
obtained
+=
PAGE_SIZE
;
obtained
+=
PAGE_SIZE
;
if
(
obtained
>=
needed
)
if
(
obtained
>=
needed
)
...
@@ -817,7 +814,6 @@ static void refill_freelist(int size)
...
@@ -817,7 +814,6 @@ static void refill_freelist(int size)
*/
*/
while
(
obtained
<
(
needed
>>
1
)
&&
while
(
obtained
<
(
needed
>>
1
)
&&
nr_free_pages
>
freepages
.
min
+
5
&&
nr_free_pages
>
freepages
.
min
+
5
&&
BUFFER_MEM
<
(
buffer_mem
.
max_percent
*
num_physpages
/
100
)
&&
grow_buffers
(
GFP_BUFFER
,
size
))
grow_buffers
(
GFP_BUFFER
,
size
))
obtained
+=
PAGE_SIZE
;
obtained
+=
PAGE_SIZE
;
...
@@ -1707,11 +1703,16 @@ void show_buffers(void)
...
@@ -1707,11 +1703,16 @@ void show_buffers(void)
*/
*/
void
buffer_init
(
void
)
void
buffer_init
(
void
)
{
{
hash_table
=
(
struct
buffer_head
**
)
int
order
=
5
;
/* Currently maximum order.. */
__get_free_pages
(
GFP_ATOMIC
,
HASH_PAGES_ORDER
);
unsigned
int
nr_hash
;
nr_hash
=
(
1UL
<<
order
)
*
PAGE_SIZE
/
sizeof
(
struct
buffer_head
*
);
hash_table
=
(
struct
buffer_head
**
)
__get_free_pages
(
GFP_ATOMIC
,
order
);
if
(
!
hash_table
)
if
(
!
hash_table
)
panic
(
"Failed to allocate buffer hash table
\n
"
);
panic
(
"Failed to allocate buffer hash table
\n
"
);
memset
(
hash_table
,
0
,
NR_HASH
*
sizeof
(
struct
buffer_head
*
));
memset
(
hash_table
,
0
,
nr_hash
*
sizeof
(
struct
buffer_head
*
));
bh_hash_mask
=
nr_hash
-
1
;
bh_cachep
=
kmem_cache_create
(
"buffer_head"
,
bh_cachep
=
kmem_cache_create
(
"buffer_head"
,
sizeof
(
struct
buffer_head
),
sizeof
(
struct
buffer_head
),
...
...
include/linux/swap.h
View file @
b884a92a
...
@@ -39,7 +39,6 @@ extern atomic_t nr_async_pages;
...
@@ -39,7 +39,6 @@ extern atomic_t nr_async_pages;
extern
struct
inode
swapper_inode
;
extern
struct
inode
swapper_inode
;
extern
unsigned
long
page_cache_size
;
extern
unsigned
long
page_cache_size
;
extern
int
buffermem
;
extern
int
buffermem
;
#define BUFFER_MEM ((buffermem >> PAGE_SHIFT) + page_cache_size)
/* Incomplete types for prototype declarations: */
/* Incomplete types for prototype declarations: */
struct
task_struct
;
struct
task_struct
;
...
...
kernel/sysctl.c
View file @
b884a92a
...
@@ -191,7 +191,7 @@ static ctl_table vm_table[] = {
...
@@ -191,7 +191,7 @@ static ctl_table vm_table[] = {
{
VM_SWAPCTL
,
"swapctl"
,
{
VM_SWAPCTL
,
"swapctl"
,
&
swap_control
,
sizeof
(
swap_control_t
),
0600
,
NULL
,
&
proc_dointvec
},
&
swap_control
,
sizeof
(
swap_control_t
),
0600
,
NULL
,
&
proc_dointvec
},
{
VM_SWAPOUT
,
"swapout_interval"
,
{
VM_SWAPOUT
,
"swapout_interval"
,
&
swapout_interval
,
sizeof
(
int
),
0600
,
NULL
,
&
proc_dointvec
_jiffies
},
&
swapout_interval
,
sizeof
(
int
),
0600
,
NULL
,
&
proc_dointvec
},
{
VM_FREEPG
,
"freepages"
,
{
VM_FREEPG
,
"freepages"
,
&
freepages
,
sizeof
(
freepages_t
),
0600
,
NULL
,
&
proc_dointvec
},
&
freepages
,
sizeof
(
freepages_t
),
0600
,
NULL
,
&
proc_dointvec
},
{
VM_BDFLUSH
,
"bdflush"
,
&
bdf_prm
,
9
*
sizeof
(
int
),
0600
,
NULL
,
{
VM_BDFLUSH
,
"bdflush"
,
&
bdf_prm
,
9
*
sizeof
(
int
),
0600
,
NULL
,
...
...
mm/filemap.c
View file @
b884a92a
...
@@ -150,6 +150,10 @@ int shrink_mmap(int priority, int gfp_mask)
...
@@ -150,6 +150,10 @@ int shrink_mmap(int priority, int gfp_mask)
}
}
tmp
=
tmp
->
b_this_page
;
tmp
=
tmp
->
b_this_page
;
}
while
(
tmp
!=
bh
);
}
while
(
tmp
!=
bh
);
/* Refuse to swap out all buffer pages */
if
((
buffermem
>>
PAGE_SHIFT
)
*
100
>
(
buffer_mem
.
min_percent
*
num_physpages
))
goto
next
;
}
}
/* We can't throw away shared pages, but we do mark
/* We can't throw away shared pages, but we do mark
...
...
mm/page_alloc.c
View file @
b884a92a
...
@@ -124,6 +124,7 @@ static spinlock_t page_alloc_lock;
...
@@ -124,6 +124,7 @@ static spinlock_t page_alloc_lock;
*/
*/
int
free_memory_available
(
int
nr
)
int
free_memory_available
(
int
nr
)
{
{
int
retval
=
0
;
unsigned
long
flags
;
unsigned
long
flags
;
struct
free_area_struct
*
list
=
NULL
;
struct
free_area_struct
*
list
=
NULL
;
...
@@ -141,10 +142,11 @@ int free_memory_available(int nr)
...
@@ -141,10 +142,11 @@ int free_memory_available(int nr)
if
(
list
->
next
->
next
==
memory_head
(
list
))
if
(
list
->
next
->
next
==
memory_head
(
list
))
continue
;
continue
;
/* More than one item? We're ok */
/* More than one item? We're ok */
retval
=
nr
+
1
;
break
;
break
;
}
while
(
--
nr
>=
0
);
}
while
(
--
nr
>=
0
);
spin_unlock_irqrestore
(
&
page_alloc_lock
,
flags
);
spin_unlock_irqrestore
(
&
page_alloc_lock
,
flags
);
return
nr
+
1
;
return
retval
;
}
}
static
inline
void
free_pages_ok
(
unsigned
long
map_nr
,
unsigned
long
order
)
static
inline
void
free_pages_ok
(
unsigned
long
map_nr
,
unsigned
long
order
)
...
...
mm/swap.c
View file @
b884a92a
...
@@ -67,8 +67,8 @@ swap_control_t swap_control = {
...
@@ -67,8 +67,8 @@ swap_control_t swap_control = {
swapstat_t
swapstats
=
{
0
};
swapstat_t
swapstats
=
{
0
};
buffer_mem_t
buffer_mem
=
{
buffer_mem_t
buffer_mem
=
{
6
,
/* minimum percent buffer + cache memory
*/
3
,
/* minimum percent buffer
*/
20
,
/* borrow percent buffer + cache memory
*/
10
,
/* borrow percent buffer
*/
90
/* maximum percent buffer + cache memory
*/
30
/* maximum percent buffer
*/
};
};
mm/vmscan.c
View file @
b884a92a
...
@@ -31,7 +31,7 @@
...
@@ -31,7 +31,7 @@
/*
/*
* When are we next due for a page scan?
* When are we next due for a page scan?
*/
*/
static
int
next_swap_jiffies
=
0
;
static
unsigned
long
next_swap_jiffies
=
0
;
/*
/*
* How often do we do a pageout scan during normal conditions?
* How often do we do a pageout scan during normal conditions?
...
@@ -451,14 +451,13 @@ static inline int do_try_to_free_page(int gfp_mask)
...
@@ -451,14 +451,13 @@ static inline int do_try_to_free_page(int gfp_mask)
stop
=
3
;
stop
=
3
;
if
(
gfp_mask
&
__GFP_WAIT
)
if
(
gfp_mask
&
__GFP_WAIT
)
stop
=
0
;
stop
=
0
;
if
(
BUFFER_MEM
>
buffer_mem
.
borrow_percent
*
num_physpages
/
100
)
if
(
(
buffermem
>>
PAGE_SHIFT
)
*
100
>
buffer_mem
.
borrow_percent
*
num_physpages
)
state
=
0
;
state
=
0
;
switch
(
state
)
{
switch
(
state
)
{
do
{
do
{
case
0
:
case
0
:
if
(
BUFFER_MEM
>
(
buffer_mem
.
min_percent
*
num_physpages
/
100
)
&&
if
(
shrink_mmap
(
i
,
gfp_mask
))
shrink_mmap
(
i
,
gfp_mask
))
return
1
;
return
1
;
state
=
1
;
state
=
1
;
case
1
:
case
1
:
...
@@ -547,18 +546,30 @@ int kswapd(void *unused)
...
@@ -547,18 +546,30 @@ int kswapd(void *unused)
run_task_queue
(
&
tq_disk
);
run_task_queue
(
&
tq_disk
);
schedule
();
schedule
();
swapstats
.
wakeups
++
;
swapstats
.
wakeups
++
;
/* Do the background pageout:
* When we've got loads of memory, we try
/*
* (freepages.high - nr_free_pages) times to
* Do the background pageout: be
* free memory. As memory gets tighter, kswapd
* more aggressive if we're really
* gets more and more agressive. -- Rik.
* low on free memory.
*
* Normally this is called 4 times
* a second if we need more memory,
* so this has a normal rate of
* X*4 pages of memory free'd per
* second. That rate goes up when
*
* - we're really low on memory (we get woken
* up a lot more)
* - other processes fail to allocate memory,
* at which time they try to do their own
* freeing.
*
* A "tries" value of 50 means up to 200 pages
* per second (1.6MB/s). This should be a /proc
* thing.
*/
*/
tries
=
freepages
.
high
-
nr_free_pages
;
tries
=
50
;
if
(
tries
<
freepages
.
min
)
{
tries
=
freepages
.
min
;
}
if
(
nr_free_pages
<
freepages
.
low
)
tries
<<=
1
;
while
(
tries
--
)
{
while
(
tries
--
)
{
int
gfp_mask
;
int
gfp_mask
;
...
@@ -583,7 +594,6 @@ int kswapd(void *unused)
...
@@ -583,7 +594,6 @@ int kswapd(void *unused)
/*
/*
* The swap_tick function gets called on every clock tick.
* The swap_tick function gets called on every clock tick.
*/
*/
void
swap_tick
(
void
)
void
swap_tick
(
void
)
{
{
unsigned
long
now
,
want
;
unsigned
long
now
,
want
;
...
@@ -604,13 +614,13 @@ void swap_tick(void)
...
@@ -604,13 +614,13 @@ void swap_tick(void)
case
0
:
case
0
:
want
=
now
;
want
=
now
;
/* Fall through */
/* Fall through */
case
1
...
2
:
case
1
...
3
:
want_wakeup
=
1
;
want_wakeup
=
1
;
default:
default:
}
}
if
((
long
)
(
now
-
want
)
>=
0
)
{
if
((
long
)
(
now
-
want
)
>=
0
)
{
if
(
want_wakeup
||
(
num_physpages
*
buffer_mem
.
max_percent
/
100
)
<
BUFFER_MEM
)
{
if
(
want_wakeup
||
(
num_physpages
*
buffer_mem
.
max_percent
)
<
(
buffermem
>>
PAGE_SHIFT
)
*
100
)
{
/* Set the next wake-up time */
/* Set the next wake-up time */
next_swap_jiffies
=
now
+
swapout_interval
;
next_swap_jiffies
=
now
+
swapout_interval
;
wake_up
(
&
kswapd_wait
);
wake_up
(
&
kswapd_wait
);
...
...
net/core/datagram.c
View file @
b884a92a
...
@@ -132,15 +132,13 @@ struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock,
...
@@ -132,15 +132,13 @@ struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock,
unsigned
long
flags
;
unsigned
long
flags
;
save_flags
(
flags
);
save_flags
(
flags
);
cli
();
cli
();
skb
=
skb_peek
(
&
sk
->
receive_queue
);
skb
=
skb_peek
(
&
sk
->
receive_queue
);
if
(
skb
!=
NULL
)
if
(
skb
!=
NULL
)
atomic_inc
(
&
skb
->
users
);
atomic_inc
(
&
skb
->
users
);
restore_flags
(
flags
);
restore_flags
(
flags
);
if
(
skb
==
NULL
)
/* shouldn't happen but .. */
}
else
goto
restart
;
skb
=
skb_dequeue
(
&
sk
->
receive_queue
);
return
skb
;
}
skb
=
skb_dequeue
(
&
sk
->
receive_queue
);
if
(
!
skb
)
/* Avoid race if someone beats us to the data */
if
(
!
skb
)
/* Avoid race if someone beats us to the data */
goto
restart
;
goto
restart
;
return
skb
;
return
skb
;
...
@@ -163,30 +161,23 @@ void skb_free_datagram(struct sock * sk, struct sk_buff *skb)
...
@@ -163,30 +161,23 @@ void skb_free_datagram(struct sock * sk, struct sk_buff *skb)
int
skb_copy_datagram
(
struct
sk_buff
*
skb
,
int
offset
,
char
*
to
,
int
size
)
int
skb_copy_datagram
(
struct
sk_buff
*
skb
,
int
offset
,
char
*
to
,
int
size
)
{
{
int
err
;
int
err
=
-
EFAULT
;
err
=
copy_to_user
(
to
,
skb
->
h
.
raw
+
offset
,
size
);
if
(
err
)
if
(
!
copy_to_user
(
to
,
skb
->
h
.
raw
+
offset
,
size
))
{
err
=
0
;
err
=
-
EFAULT
;
}
return
err
;
return
err
;
}
}
/*
/*
* Copy a datagram to an iovec.
* Copy a datagram to an iovec.
* Note: the iovec is modified during the copy.
*/
*/
int
skb_copy_datagram_iovec
(
struct
sk_buff
*
skb
,
int
offset
,
struct
iovec
*
to
,
int
skb_copy_datagram_iovec
(
struct
sk_buff
*
skb
,
int
offset
,
struct
iovec
*
to
,
int
size
)
int
size
)
{
{
int
err
;
return
memcpy_toiovec
(
to
,
skb
->
h
.
raw
+
offset
,
size
);
err
=
memcpy_toiovec
(
to
,
skb
->
h
.
raw
+
offset
,
size
);
if
(
err
)
{
err
=
-
EFAULT
;
}
return
err
;
}
}
/*
/*
...
...
net/core/iovec.c
View file @
b884a92a
...
@@ -30,7 +30,6 @@
...
@@ -30,7 +30,6 @@
/*
/*
* Verify iovec
* Verify iovec
* verify area does a simple check for completly bogus addresses
*
*
* Save time not doing verify_area. copy_*_user will make this work
* Save time not doing verify_area. copy_*_user will make this work
* in any case.
* in any case.
...
@@ -79,22 +78,21 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode)
...
@@ -79,22 +78,21 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode)
}
}
/*
/*
* Copy kernel to iovec.
* Copy kernel to iovec.
Returns -EFAULT on error.
*
*
* Note: this modifies the original iovec.
* Note: this modifies the original iovec.
*/
*/
int
memcpy_toiovec
(
struct
iovec
*
iov
,
unsigned
char
*
kdata
,
int
len
)
int
memcpy_toiovec
(
struct
iovec
*
iov
,
unsigned
char
*
kdata
,
int
len
)
{
{
int
err
;
int
err
=
-
EFAULT
;
while
(
len
>
0
)
while
(
len
>
0
)
{
{
if
(
iov
->
iov_len
)
if
(
iov
->
iov_len
)
{
{
int
copy
=
min
(
iov
->
iov_len
,
len
);
int
copy
=
min
(
iov
->
iov_len
,
len
);
err
=
copy_to_user
(
iov
->
iov_base
,
kdata
,
copy
);
if
(
copy_to_user
(
iov
->
iov_base
,
kdata
,
copy
))
if
(
err
)
goto
out
;
goto
out
;
kdata
+=
copy
;
kdata
+=
copy
;
len
-=
copy
;
len
-=
copy
;
...
@@ -109,7 +107,7 @@ int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
...
@@ -109,7 +107,7 @@ int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
}
}
/*
/*
* Copy iovec to kernel.
* Copy iovec to kernel.
Returns -EFAULT on error.
*
*
* Note: this modifies the original iovec.
* Note: this modifies the original iovec.
*/
*/
...
@@ -147,35 +145,23 @@ int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
...
@@ -147,35 +145,23 @@ int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
{
{
int
err
=
-
EFAULT
;
int
err
=
-
EFAULT
;
while
(
offset
>
0
)
/* Skip over the finished iovecs */
while
(
offset
>=
iov
->
iov_len
)
{
{
if
(
offset
>
iov
->
iov_len
)
offset
-=
iov
->
iov_len
;
{
offset
-=
iov
->
iov_len
;
}
else
{
u8
*
base
=
iov
->
iov_base
+
offset
;
int
copy
=
min
(
len
,
iov
->
iov_len
-
offset
);
offset
=
0
;
if
(
copy_from_user
(
kdata
,
base
,
copy
))
goto
out
;
len
-=
copy
;
kdata
+=
copy
;
}
iov
++
;
iov
++
;
}
}
while
(
len
>
0
)
while
(
len
>
0
)
{
{
int
copy
=
min
(
len
,
iov
->
iov_len
);
u8
*
base
=
iov
->
iov_base
+
offset
;
int
copy
=
min
(
len
,
iov
->
iov_len
-
offset
);
if
(
copy_from_user
(
kdata
,
iov
->
iov_base
,
copy
))
offset
=
0
;
if
(
copy_from_user
(
kdata
,
base
,
copy
))
goto
out
;
goto
out
;
len
-=
copy
;
len
-=
copy
;
kdata
+=
copy
;
kdata
+=
copy
;
iov
++
;
iov
++
;
}
}
err
=
0
;
err
=
0
;
...
@@ -195,51 +181,22 @@ int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
...
@@ -195,51 +181,22 @@ int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
int
csum_partial_copy_fromiovecend
(
unsigned
char
*
kdata
,
struct
iovec
*
iov
,
int
csum_partial_copy_fromiovecend
(
unsigned
char
*
kdata
,
struct
iovec
*
iov
,
int
offset
,
unsigned
int
len
,
int
*
csump
)
int
offset
,
unsigned
int
len
,
int
*
csump
)
{
{
int
partial_cnt
=
0
;
int
csum
=
*
csump
;
int
err
=
0
;
int
partial_cnt
=
0
,
err
=
0
;
int
csum
;
do
{
/* Skip over the finished iovecs */
int
copy
=
iov
->
iov_len
-
offset
;
while
(
offset
>=
iov
->
iov_len
)
{
if
(
copy
>
0
)
{
offset
-=
iov
->
iov_len
;
u8
*
base
=
iov
->
iov_base
+
offset
;
/* Normal case (single iov component) is fastly detected */
if
(
len
<=
copy
)
{
*
csump
=
csum_and_copy_from_user
(
base
,
kdata
,
len
,
*
csump
,
&
err
);
goto
out
;
}
partial_cnt
=
copy
%
4
;
if
(
partial_cnt
)
{
copy
-=
partial_cnt
;
if
(
copy_from_user
(
kdata
+
copy
,
base
+
copy
,
partial_cnt
))
goto
out_fault
;
}
*
csump
=
csum_and_copy_from_user
(
base
,
kdata
,
copy
,
*
csump
,
&
err
);
if
(
err
)
goto
out
;
len
-=
copy
+
partial_cnt
;
kdata
+=
copy
+
partial_cnt
;
iov
++
;
break
;
}
iov
++
;
iov
++
;
offset
=
-
copy
;
}
}
while
(
offset
>
0
);
csum
=
*
csump
;
while
(
len
>
0
)
while
(
len
>
0
)
{
{
u8
*
base
=
iov
->
iov_base
;
u8
*
base
=
iov
->
iov_base
+
offset
;
unsigned
int
copy
=
min
(
len
,
iov
->
iov_len
);
unsigned
int
copy
=
min
(
len
,
iov
->
iov_len
-
offset
);
offset
=
0
;
/* There is a remnant from previous iov. */
/* There is a remnant from previous iov. */
if
(
partial_cnt
)
if
(
partial_cnt
)
{
{
...
...
net/packet/af_packet.c
View file @
b884a92a
...
@@ -262,9 +262,9 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg, int len,
...
@@ -262,9 +262,9 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg, int len,
struct
scm_cookie
*
scm
)
struct
scm_cookie
*
scm
)
{
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
sk
=
sock
->
sk
;
struct
sockaddr_pkt
*
saddr
=
(
struct
sockaddr_pkt
*
)
msg
->
msg_name
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
struct
device
*
dev
;
struct
device
*
dev
;
struct
sockaddr_pkt
*
saddr
=
(
struct
sockaddr_pkt
*
)
msg
->
msg_name
;
unsigned
short
proto
=
0
;
unsigned
short
proto
=
0
;
int
err
;
int
err
;
...
@@ -309,6 +309,7 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg, int len,
...
@@ -309,6 +309,7 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg, int len,
return
-
EMSGSIZE
;
return
-
EMSGSIZE
;
dev_lock_list
();
dev_lock_list
();
err
=
-
ENOBUFS
;
skb
=
sock_wmalloc
(
sk
,
len
+
dev
->
hard_header_len
+
15
,
0
,
GFP_KERNEL
);
skb
=
sock_wmalloc
(
sk
,
len
+
dev
->
hard_header_len
+
15
,
0
,
GFP_KERNEL
);
/*
/*
...
@@ -318,10 +319,7 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg, int len,
...
@@ -318,10 +319,7 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg, int len,
*/
*/
if
(
skb
==
NULL
)
if
(
skb
==
NULL
)
{
goto
out_unlock
;
dev_unlock_list
();
return
(
-
ENOBUFS
);
}
/*
/*
* Fill it in
* Fill it in
...
@@ -339,36 +337,32 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg, int len,
...
@@ -339,36 +337,32 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg, int len,
skb
->
data
-=
dev
->
hard_header_len
;
skb
->
data
-=
dev
->
hard_header_len
;
skb
->
tail
-=
dev
->
hard_header_len
;
skb
->
tail
-=
dev
->
hard_header_len
;
}
}
/* Returns -EFAULT on error */
err
=
memcpy_fromiovec
(
skb_put
(
skb
,
len
),
msg
->
msg_iov
,
len
);
err
=
memcpy_fromiovec
(
skb_put
(
skb
,
len
),
msg
->
msg_iov
,
len
);
skb
->
protocol
=
proto
;
skb
->
protocol
=
proto
;
skb
->
dev
=
dev
;
skb
->
dev
=
dev
;
skb
->
priority
=
sk
->
priority
;
skb
->
priority
=
sk
->
priority
;
dev_unlock_list
();
if
(
err
)
goto
out_free
;
err
=
-
ENETDOWN
;
if
(
!
(
dev
->
flags
&
IFF_UP
))
goto
out_free
;
/*
/*
* Now send it
* Now send it
*/
*/
if
(
err
)
dev_unlock_list
();
{
err
=
-
EFAULT
;
}
else
{
if
(
!
(
dev
->
flags
&
IFF_UP
))
{
err
=
-
ENETDOWN
;
}
}
if
(
err
)
{
kfree_skb
(
skb
);
return
err
;
}
dev_queue_xmit
(
skb
);
dev_queue_xmit
(
skb
);
return
(
len
);
return
(
len
);
out_free:
kfree_skb
(
skb
);
out_unlock:
dev_unlock_list
();
return
err
;
}
}
#endif
#endif
...
@@ -434,13 +428,12 @@ static int packet_sendmsg(struct socket *sock, struct msghdr *msg, int len,
...
@@ -434,13 +428,12 @@ static int packet_sendmsg(struct socket *sock, struct msghdr *msg, int len,
struct
scm_cookie
*
scm
)
struct
scm_cookie
*
scm
)
{
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
sk
=
sock
->
sk
;
struct
sockaddr_ll
*
saddr
=
(
struct
sockaddr_ll
*
)
msg
->
msg_name
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
struct
device
*
dev
;
struct
device
*
dev
;
struct
sockaddr_ll
*
saddr
=
(
struct
sockaddr_ll
*
)
msg
->
msg_name
;
unsigned
short
proto
;
unsigned
short
proto
;
int
ifindex
;
unsigned
char
*
addr
;
int
err
;
int
ifindex
,
err
,
reserve
=
0
;
int
reserve
=
0
;
/*
/*
* Check the flags.
* Check the flags.
...
@@ -454,13 +447,15 @@ static int packet_sendmsg(struct socket *sock, struct msghdr *msg, int len,
...
@@ -454,13 +447,15 @@ static int packet_sendmsg(struct socket *sock, struct msghdr *msg, int len,
*/
*/
if
(
saddr
==
NULL
)
{
if
(
saddr
==
NULL
)
{
ifindex
=
sk
->
protinfo
.
af_packet
->
ifindex
;
ifindex
=
sk
->
protinfo
.
af_packet
->
ifindex
;
proto
=
sk
->
num
;
proto
=
sk
->
num
;
addr
=
NULL
;
}
else
{
}
else
{
if
(
msg
->
msg_namelen
<
sizeof
(
struct
sockaddr_ll
))
if
(
msg
->
msg_namelen
<
sizeof
(
struct
sockaddr_ll
))
return
-
EINVAL
;
return
-
EINVAL
;
ifindex
=
saddr
->
sll_ifindex
;
ifindex
=
saddr
->
sll_ifindex
;
proto
=
saddr
->
sll_protocol
;
proto
=
saddr
->
sll_protocol
;
addr
=
saddr
->
sll_addr
;
}
}
dev
=
dev_get_by_index
(
ifindex
);
dev
=
dev_get_by_index
(
ifindex
);
...
@@ -474,55 +469,50 @@ static int packet_sendmsg(struct socket *sock, struct msghdr *msg, int len,
...
@@ -474,55 +469,50 @@ static int packet_sendmsg(struct socket *sock, struct msghdr *msg, int len,
dev_lock_list
();
dev_lock_list
();
skb
=
sock_alloc_send_skb
(
sk
,
len
+
dev
->
hard_header_len
+
15
,
0
,
msg
->
msg_flags
&
MSG_DONTWAIT
,
&
err
);
skb
=
sock_alloc_send_skb
(
sk
,
len
+
dev
->
hard_header_len
+
15
,
0
,
msg
->
msg_flags
&
MSG_DONTWAIT
,
&
err
);
if
(
skb
==
NULL
)
{
if
(
skb
==
NULL
)
dev_unlock_list
();
goto
out_unlock
;
return
err
;
}
skb_reserve
(
skb
,
(
dev
->
hard_header_len
+
15
)
&~
15
);
skb_reserve
(
skb
,
(
dev
->
hard_header_len
+
15
)
&~
15
);
skb
->
nh
.
raw
=
skb
->
data
;
skb
->
nh
.
raw
=
skb
->
data
;
if
(
dev
->
hard_header
)
{
if
(
dev
->
hard_header
)
{
if
(
dev
->
hard_header
(
skb
,
dev
,
ntohs
(
proto
),
int
res
;
saddr
?
saddr
->
sll_addr
:
NULL
,
err
=
-
EINVAL
;
NULL
,
len
)
<
0
res
=
dev
->
hard_header
(
skb
,
dev
,
ntohs
(
proto
),
addr
,
NULL
,
len
);
&&
sock
->
type
==
SOCK_DGRAM
)
{
kfree_skb
(
skb
);
dev_unlock_list
();
return
-
EINVAL
;
}
if
(
sock
->
type
!=
SOCK_DGRAM
)
{
if
(
sock
->
type
!=
SOCK_DGRAM
)
{
skb
->
tail
=
skb
->
data
;
skb
->
tail
=
skb
->
data
;
skb
->
len
=
0
;
skb
->
len
=
0
;
}
}
else
if
(
res
<
0
)
goto
out_free
;
}
}
/* Returns -EFAULT on error */
err
=
memcpy_fromiovec
(
skb_put
(
skb
,
len
),
msg
->
msg_iov
,
len
);
err
=
memcpy_fromiovec
(
skb_put
(
skb
,
len
),
msg
->
msg_iov
,
len
);
skb
->
protocol
=
proto
;
skb
->
protocol
=
proto
;
skb
->
dev
=
dev
;
skb
->
dev
=
dev
;
skb
->
priority
=
sk
->
priority
;
skb
->
priority
=
sk
->
priority
;
dev_unlock_list
();
if
(
err
)
goto
out_free
;
err
=
-
ENETDOWN
;
if
(
!
(
dev
->
flags
&
IFF_UP
))
goto
out_free
;
/*
/*
* Now send it
* Now send it
*/
*/
if
(
err
)
{
dev_unlock_list
();
err
=
-
EFAULT
;
}
else
{
if
(
!
(
dev
->
flags
&
IFF_UP
))
err
=
-
ENETDOWN
;
}
if
(
err
)
{
kfree_skb
(
skb
);
return
err
;
}
dev_queue_xmit
(
skb
);
dev_queue_xmit
(
skb
);
return
(
len
);
return
(
len
);
out_free:
kfree_skb
(
skb
);
out_unlock:
dev_unlock_list
();
return
err
;
}
}
static
void
packet_destroy_timer
(
unsigned
long
data
)
static
void
packet_destroy_timer
(
unsigned
long
data
)
...
@@ -699,6 +689,7 @@ static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len
...
@@ -699,6 +689,7 @@ static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len
static
int
packet_create
(
struct
socket
*
sock
,
int
protocol
)
static
int
packet_create
(
struct
socket
*
sock
,
int
protocol
)
{
{
struct
sock
*
sk
;
struct
sock
*
sk
;
int
err
;
if
(
!
suser
())
if
(
!
suser
())
return
-
EPERM
;
return
-
EPERM
;
...
@@ -711,27 +702,23 @@ static int packet_create(struct socket *sock, int protocol)
...
@@ -711,27 +702,23 @@ static int packet_create(struct socket *sock, int protocol)
sock
->
state
=
SS_UNCONNECTED
;
sock
->
state
=
SS_UNCONNECTED
;
MOD_INC_USE_COUNT
;
MOD_INC_USE_COUNT
;
err
=
-
ENOBUFS
;
sk
=
sk_alloc
(
AF_PACKET
,
GFP_KERNEL
,
1
);
sk
=
sk_alloc
(
AF_PACKET
,
GFP_KERNEL
,
1
);
if
(
sk
==
NULL
)
{
if
(
sk
==
NULL
)
MOD_DEC_USE_COUNT
;
goto
out
;
return
-
ENOBUFS
;
}
sk
->
reuse
=
1
;
sk
->
reuse
=
1
;
sock
->
ops
=
&
packet_ops
;
#ifdef CONFIG_SOCK_PACKET
#ifdef CONFIG_SOCK_PACKET
if
(
sock
->
type
==
SOCK_PACKET
)
if
(
sock
->
type
==
SOCK_PACKET
)
sock
->
ops
=
&
packet_ops_spkt
;
sock
->
ops
=
&
packet_ops_spkt
;
else
#endif
#endif
sock
->
ops
=
&
packet_ops
;
sock_init_data
(
sock
,
sk
);
sock_init_data
(
sock
,
sk
);
sk
->
protinfo
.
af_packet
=
kmalloc
(
sizeof
(
struct
packet_opt
),
GFP_KERNEL
);
sk
->
protinfo
.
af_packet
=
kmalloc
(
sizeof
(
struct
packet_opt
),
GFP_KERNEL
);
if
(
sk
->
protinfo
.
af_packet
==
NULL
)
{
if
(
sk
->
protinfo
.
af_packet
==
NULL
)
sk_free
(
sk
);
goto
out_free
;
MOD_DEC_USE_COUNT
;
return
-
ENOBUFS
;
}
memset
(
sk
->
protinfo
.
af_packet
,
0
,
sizeof
(
struct
packet_opt
));
memset
(
sk
->
protinfo
.
af_packet
,
0
,
sizeof
(
struct
packet_opt
));
sk
->
zapped
=
0
;
sk
->
zapped
=
0
;
sk
->
family
=
AF_PACKET
;
sk
->
family
=
AF_PACKET
;
...
@@ -741,13 +728,11 @@ static int packet_create(struct socket *sock, int protocol)
...
@@ -741,13 +728,11 @@ static int packet_create(struct socket *sock, int protocol)
* Attach a protocol block
* Attach a protocol block
*/
*/
sk
->
protinfo
.
af_packet
->
prot_hook
.
func
=
packet_rcv
;
#ifdef CONFIG_SOCK_PACKET
#ifdef CONFIG_SOCK_PACKET
if
(
sock
->
type
==
SOCK_PACKET
)
if
(
sock
->
type
==
SOCK_PACKET
)
sk
->
protinfo
.
af_packet
->
prot_hook
.
func
=
packet_rcv_spkt
;
sk
->
protinfo
.
af_packet
->
prot_hook
.
func
=
packet_rcv_spkt
;
else
#endif
#endif
sk
->
protinfo
.
af_packet
->
prot_hook
.
func
=
packet_rcv
;
sk
->
protinfo
.
af_packet
->
prot_hook
.
data
=
(
void
*
)
sk
;
sk
->
protinfo
.
af_packet
->
prot_hook
.
data
=
(
void
*
)
sk
;
if
(
protocol
)
{
if
(
protocol
)
{
...
@@ -758,6 +743,12 @@ static int packet_create(struct socket *sock, int protocol)
...
@@ -758,6 +743,12 @@ static int packet_create(struct socket *sock, int protocol)
sklist_insert_socket
(
&
packet_sklist
,
sk
);
sklist_insert_socket
(
&
packet_sklist
,
sk
);
return
(
0
);
return
(
0
);
out_free:
sk_free
(
sk
);
out:
MOD_DEC_USE_COUNT
;
return
err
;
}
}
/*
/*
...
@@ -832,10 +823,8 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, int len,
...
@@ -832,10 +823,8 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, int len,
/* We can't use skb_copy_datagram here */
/* We can't use skb_copy_datagram here */
err
=
memcpy_toiovec
(
msg
->
msg_iov
,
skb
->
data
,
copied
);
err
=
memcpy_toiovec
(
msg
->
msg_iov
,
skb
->
data
,
copied
);
if
(
err
)
{
if
(
err
)
err
=
-
EFAULT
;
goto
out_free
;
goto
out_free
;
}
sk
->
stamp
=
skb
->
stamp
;
sk
->
stamp
=
skb
->
stamp
;
if
(
msg
->
msg_name
)
if
(
msg
->
msg_name
)
...
@@ -932,37 +921,39 @@ static void packet_dev_mclist(struct device *dev, struct packet_mclist *i, int w
...
@@ -932,37 +921,39 @@ static void packet_dev_mclist(struct device *dev, struct packet_mclist *i, int w
static
int
packet_mc_add
(
struct
sock
*
sk
,
struct
packet_mreq
*
mreq
)
static
int
packet_mc_add
(
struct
sock
*
sk
,
struct
packet_mreq
*
mreq
)
{
{
int
err
;
struct
packet_mclist
*
ml
,
*
i
;
struct
packet_mclist
*
ml
,
*
i
;
struct
device
*
dev
;
struct
device
*
dev
;
int
err
;
rtnl_shlock
();
rtnl_shlock
();
dev
=
dev_get_by_index
(
mreq
->
mr_ifindex
);
i
=
NULL
;
err
=
-
ENODEV
;
err
=
-
ENODEV
;
dev
=
dev_get_by_index
(
mreq
->
mr_ifindex
);
if
(
!
dev
)
if
(
!
dev
)
goto
done
;
goto
done
;
err
=
-
EINVAL
;
err
=
-
EINVAL
;
if
(
mreq
->
mr_alen
>
dev
->
addr_len
)
if
(
mreq
->
mr_alen
>
dev
->
addr_len
)
goto
done
;
goto
done
;
err
=
-
ENOBUFS
;
i
=
(
struct
packet_mclist
*
)
kmalloc
(
sizeof
(
*
i
),
GFP_KERNEL
);
i
=
(
struct
packet_mclist
*
)
kmalloc
(
sizeof
(
*
i
),
GFP_KERNEL
);
if
(
i
==
NULL
)
goto
done
;
err
=
0
;
for
(
ml
=
sk
->
protinfo
.
af_packet
->
mclist
;
ml
;
ml
=
ml
->
next
)
{
for
(
ml
=
sk
->
protinfo
.
af_packet
->
mclist
;
ml
;
ml
=
ml
->
next
)
{
if
(
ml
->
ifindex
==
mreq
->
mr_ifindex
&&
if
(
ml
->
ifindex
==
mreq
->
mr_ifindex
&&
ml
->
type
==
mreq
->
mr_type
&&
ml
->
type
==
mreq
->
mr_type
&&
ml
->
alen
==
mreq
->
mr_alen
&&
ml
->
alen
==
mreq
->
mr_alen
&&
memcmp
(
ml
->
addr
,
mreq
->
mr_address
,
ml
->
alen
)
==
0
)
{
memcmp
(
ml
->
addr
,
mreq
->
mr_address
,
ml
->
alen
)
==
0
)
{
ml
->
count
++
;
ml
->
count
++
;
err
=
0
;
/* Free the new element ... */
kfree
(
i
);
goto
done
;
goto
done
;
}
}
}
}
err
=
-
ENOBUFS
;
if
(
i
==
NULL
)
goto
done
;
i
->
type
=
mreq
->
mr_type
;
i
->
type
=
mreq
->
mr_type
;
i
->
ifindex
=
mreq
->
mr_ifindex
;
i
->
ifindex
=
mreq
->
mr_ifindex
;
i
->
alen
=
mreq
->
mr_alen
;
i
->
alen
=
mreq
->
mr_alen
;
...
@@ -971,13 +962,9 @@ static int packet_mc_add(struct sock *sk, struct packet_mreq *mreq)
...
@@ -971,13 +962,9 @@ static int packet_mc_add(struct sock *sk, struct packet_mreq *mreq)
i
->
next
=
sk
->
protinfo
.
af_packet
->
mclist
;
i
->
next
=
sk
->
protinfo
.
af_packet
->
mclist
;
sk
->
protinfo
.
af_packet
->
mclist
=
i
;
sk
->
protinfo
.
af_packet
->
mclist
=
i
;
packet_dev_mc
(
dev
,
i
,
+
1
);
packet_dev_mc
(
dev
,
i
,
+
1
);
i
=
NULL
;
err
=
0
;
done:
done:
rtnl_shunlock
();
rtnl_shunlock
();
if
(
i
)
kfree
(
i
);
return
err
;
return
err
;
}
}
...
@@ -1109,13 +1096,12 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg
...
@@ -1109,13 +1096,12 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg
case
FIOGETOWN
:
case
FIOGETOWN
:
case
SIOCGPGRP
:
case
SIOCGPGRP
:
return
put_user
(
sk
->
proc
,
(
int
*
)
arg
);
return
put_user
(
sk
->
proc
,
(
int
*
)
arg
);
return
(
0
);
case
SIOCGSTAMP
:
case
SIOCGSTAMP
:
if
(
sk
->
stamp
.
tv_sec
==
0
)
if
(
sk
->
stamp
.
tv_sec
==
0
)
return
-
ENOENT
;
return
-
ENOENT
;
err
=
copy_to_user
((
void
*
)
arg
,
&
sk
->
stamp
,
sizeof
(
struct
timeval
))
;
err
=
-
EFAULT
;
if
(
err
)
if
(
!
copy_to_user
((
void
*
)
arg
,
&
sk
->
stamp
,
sizeof
(
struct
timeval
))
)
err
=
-
EFAULT
;
err
=
0
;
return
err
;
return
err
;
case
SIOCGIFFLAGS
:
case
SIOCGIFFLAGS
:
#ifndef CONFIG_INET
#ifndef CONFIG_INET
...
...
net/socket.c
View file @
b884a92a
...
@@ -1142,19 +1142,21 @@ asmlinkage int sys_sendmsg(int fd, struct msghdr *msg, unsigned flags)
...
@@ -1142,19 +1142,21 @@ asmlinkage int sys_sendmsg(int fd, struct msghdr *msg, unsigned flags)
char
address
[
MAX_SOCK_ADDR
];
char
address
[
MAX_SOCK_ADDR
];
struct
iovec
iov
[
UIO_FASTIOV
];
struct
iovec
iov
[
UIO_FASTIOV
];
unsigned
char
ctl
[
sizeof
(
struct
cmsghdr
)
+
20
];
/* 20 is size of ipv6_pktinfo */
unsigned
char
ctl
[
sizeof
(
struct
cmsghdr
)
+
20
];
/* 20 is size of ipv6_pktinfo */
struct
msghdr
msg_sys
;
int
err
=
-
EINVAL
;
int
total_len
;
unsigned
char
*
ctl_buf
=
ctl
;
unsigned
char
*
ctl_buf
=
ctl
;
struct
msghdr
msg_sys
;
int
err
,
total_len
;
lock_kernel
();
lock_kernel
();
err
=
-
EFAULT
;
err
=
-
EFAULT
;
if
(
copy_from_user
(
&
msg_sys
,
msg
,
sizeof
(
struct
msghdr
)))
if
(
copy_from_user
(
&
msg_sys
,
msg
,
sizeof
(
struct
msghdr
)))
goto
out
;
goto
out
;
/* do not move before msg_sys is valid */
/* do not move before msg_sys is valid */
if
(
msg_sys
.
msg_iovlen
>
UIO_MAXIOV
)
err
=
-
EINVAL
;
if
(
msg_sys
.
msg_iovlen
>
UIO_MAXIOV
)
goto
out
;
goto
out
;
/* This will also move the address data into kernel space */
/* This will also move the address data into kernel space */
err
=
verify_iovec
(
&
msg_sys
,
iov
,
address
,
VERIFY_READ
);
err
=
verify_iovec
(
&
msg_sys
,
iov
,
address
,
VERIFY_READ
);
if
(
err
<
0
)
if
(
err
<
0
)
...
@@ -1164,7 +1166,7 @@ asmlinkage int sys_sendmsg(int fd, struct msghdr *msg, unsigned flags)
...
@@ -1164,7 +1166,7 @@ asmlinkage int sys_sendmsg(int fd, struct msghdr *msg, unsigned flags)
sock
=
sockfd_lookup
(
fd
,
&
err
);
sock
=
sockfd_lookup
(
fd
,
&
err
);
if
(
!
sock
)
if
(
!
sock
)
goto
out
;
goto
out
_freeiov
;
if
(
msg_sys
.
msg_controllen
)
if
(
msg_sys
.
msg_controllen
)
{
{
...
@@ -1198,9 +1200,10 @@ asmlinkage int sys_sendmsg(int fd, struct msghdr *msg, unsigned flags)
...
@@ -1198,9 +1200,10 @@ asmlinkage int sys_sendmsg(int fd, struct msghdr *msg, unsigned flags)
if
(
ctl_buf
!=
ctl
)
if
(
ctl_buf
!=
ctl
)
sock_kfree_s
(
sock
->
sk
,
ctl_buf
,
msg_sys
.
msg_controllen
);
sock_kfree_s
(
sock
->
sk
,
ctl_buf
,
msg_sys
.
msg_controllen
);
failed2:
failed2:
sockfd_put
(
sock
);
out_freeiov:
if
(
msg_sys
.
msg_iov
!=
iov
)
if
(
msg_sys
.
msg_iov
!=
iov
)
kfree
(
msg_sys
.
msg_iov
);
kfree
(
msg_sys
.
msg_iov
);
sockfd_put
(
sock
);
out:
out:
unlock_kernel
();
unlock_kernel
();
return
err
;
return
err
;
...
@@ -1229,16 +1232,13 @@ asmlinkage int sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags)
...
@@ -1229,16 +1232,13 @@ asmlinkage int sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags)
int
*
uaddr_len
;
int
*
uaddr_len
;
lock_kernel
();
lock_kernel
();
err
=-
EFAULT
;
if
(
copy_from_user
(
&
msg_sys
,
msg
,
sizeof
(
struct
msghdr
)))
if
(
copy_from_user
(
&
msg_sys
,
msg
,
sizeof
(
struct
msghdr
)))
{
err
=-
EFAULT
;
goto
out
;
goto
out
;
}
if
(
msg_sys
.
msg_iovlen
>
UIO_MAXIOV
)
err
=-
EINVAL
;
{
if
(
msg_sys
.
msg_iovlen
>
UIO_MAXIOV
)
err
=-
EINVAL
;
goto
out
;
goto
out
;
}
/*
/*
* Save the user-mode address (verify_iovec will change the
* Save the user-mode address (verify_iovec will change the
...
...
net/unix/af_unix.c
View file @
b884a92a
...
@@ -687,17 +687,19 @@ static int unix_stream_connect1(struct socket *sock, struct msghdr *msg,
...
@@ -687,17 +687,19 @@ static int unix_stream_connect1(struct socket *sock, struct msghdr *msg,
skb
=
sock_alloc_send_skb
(
sk
,
len
,
0
,
nonblock
,
&
err
);
/* Marker object */
skb
=
sock_alloc_send_skb
(
sk
,
len
,
0
,
nonblock
,
&
err
);
/* Marker object */
if
(
skb
==
NULL
)
if
(
skb
==
NULL
)
return
err
;
goto
out
;
memcpy
(
&
UNIXCB
(
skb
),
cmsg
,
sizeof
(
*
cmsg
));
memcpy
(
&
UNIXCB
(
skb
),
cmsg
,
sizeof
(
*
cmsg
));
if
(
len
)
if
(
len
)
{
memcpy_fromiovec
(
skb_put
(
skb
,
len
),
msg
->
msg_iov
,
len
);
err
=
memcpy_fromiovec
(
skb_put
(
skb
,
len
),
msg
->
msg_iov
,
len
);
if
(
err
)
goto
out_free
;
}
sk
->
state
=
TCP_CLOSE
;
sk
->
state
=
TCP_CLOSE
;
other
=
unix_find_other
(
sunaddr
,
addr_len
,
sk
->
type
,
hash
,
&
err
);
other
=
unix_find_other
(
sunaddr
,
addr_len
,
sk
->
type
,
hash
,
&
err
);
if
(
other
==
NULL
)
if
(
other
==
NULL
)
{
goto
out_free
;
kfree_skb
(
skb
);
return
err
;
}
other
->
ack_backlog
++
;
other
->
ack_backlog
++
;
unix_peer
(
sk
)
=
other
;
unix_peer
(
sk
)
=
other
;
skb_queue_tail
(
&
other
->
receive_queue
,
skb
);
skb_queue_tail
(
&
other
->
receive_queue
,
skb
);
...
@@ -738,6 +740,11 @@ static int unix_stream_connect1(struct socket *sock, struct msghdr *msg,
...
@@ -738,6 +740,11 @@ static int unix_stream_connect1(struct socket *sock, struct msghdr *msg,
if
(
!
sk
->
protinfo
.
af_unix
.
addr
)
if
(
!
sk
->
protinfo
.
af_unix
.
addr
)
unix_autobind
(
sock
);
unix_autobind
(
sock
);
return
0
;
return
0
;
out_free:
kfree_skb
(
skb
);
out:
return
err
;
}
}
...
@@ -908,8 +915,8 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, int len,
...
@@ -908,8 +915,8 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, int len,
struct
scm_cookie
*
scm
)
struct
scm_cookie
*
scm
)
{
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
sk
=
sock
->
sk
;
unix_socket
*
other
;
struct
sockaddr_un
*
sunaddr
=
msg
->
msg_name
;
struct
sockaddr_un
*
sunaddr
=
msg
->
msg_name
;
unix_socket
*
other
;
int
namelen
=
0
;
/* fake GCC */
int
namelen
=
0
;
/* fake GCC */
int
err
;
int
err
;
unsigned
hash
;
unsigned
hash
;
...
@@ -935,9 +942,8 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, int len,
...
@@ -935,9 +942,8 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, int len,
unix_autobind
(
sock
);
unix_autobind
(
sock
);
skb
=
sock_alloc_send_skb
(
sk
,
len
,
0
,
msg
->
msg_flags
&
MSG_DONTWAIT
,
&
err
);
skb
=
sock_alloc_send_skb
(
sk
,
len
,
0
,
msg
->
msg_flags
&
MSG_DONTWAIT
,
&
err
);
if
(
skb
==
NULL
)
if
(
skb
==
NULL
)
return
err
;
goto
out
;
memcpy
(
UNIXCREDS
(
skb
),
&
scm
->
creds
,
sizeof
(
struct
ucred
));
memcpy
(
UNIXCREDS
(
skb
),
&
scm
->
creds
,
sizeof
(
struct
ucred
));
UNIXCB
(
skb
).
attr
=
msg
->
msg_flags
;
UNIXCB
(
skb
).
attr
=
msg
->
msg_flags
;
...
@@ -945,7 +951,9 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, int len,
...
@@ -945,7 +951,9 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, int len,
unix_attach_fds
(
scm
,
skb
);
unix_attach_fds
(
scm
,
skb
);
skb
->
h
.
raw
=
skb
->
data
;
skb
->
h
.
raw
=
skb
->
data
;
memcpy_fromiovec
(
skb_put
(
skb
,
len
),
msg
->
msg_iov
,
len
);
err
=
memcpy_fromiovec
(
skb_put
(
skb
,
len
),
msg
->
msg_iov
,
len
);
if
(
err
)
goto
out_free
;
other
=
unix_peer
(
sk
);
other
=
unix_peer
(
sk
);
if
(
other
&&
other
->
dead
)
if
(
other
&&
other
->
dead
)
...
@@ -957,26 +965,18 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, int len,
...
@@ -957,26 +965,18 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, int len,
unix_unlock
(
other
);
unix_unlock
(
other
);
unix_peer
(
sk
)
=
NULL
;
unix_peer
(
sk
)
=
NULL
;
other
=
NULL
;
other
=
NULL
;
if
(
sunaddr
==
NULL
)
{
err
=
-
ECONNRESET
;
kfree_skb
(
skb
);
if
(
sunaddr
==
NULL
)
return
-
ECONNRESET
;
goto
out_free
;
}
}
}
if
(
!
other
)
if
(
!
other
)
{
{
other
=
unix_find_other
(
sunaddr
,
namelen
,
sk
->
type
,
hash
,
&
err
);
other
=
unix_find_other
(
sunaddr
,
namelen
,
sk
->
type
,
hash
,
&
err
);
if
(
other
==
NULL
)
if
(
other
==
NULL
)
{
goto
out_free
;
kfree_skb
(
skb
);
err
=
-
EINVAL
;
return
err
;
}
if
(
!
unix_may_send
(
sk
,
other
))
if
(
!
unix_may_send
(
sk
,
other
))
{
goto
out_unlock
;
unix_unlock
(
other
);
kfree_skb
(
skb
);
return
-
EINVAL
;
}
}
}
skb_queue_tail
(
&
other
->
receive_queue
,
skb
);
skb_queue_tail
(
&
other
->
receive_queue
,
skb
);
...
@@ -985,6 +985,13 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, int len,
...
@@ -985,6 +985,13 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, int len,
if
(
!
unix_peer
(
sk
))
if
(
!
unix_peer
(
sk
))
unix_unlock
(
other
);
unix_unlock
(
other
);
return
len
;
return
len
;
out_unlock:
unix_unlock
(
other
);
out_free:
kfree_skb
(
skb
);
out:
return
err
;
}
}
...
@@ -1267,9 +1274,7 @@ static int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg, int size
...
@@ -1267,9 +1274,7 @@ static int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg, int size
}
}
chunk
=
min
(
skb
->
len
,
size
);
chunk
=
min
(
skb
->
len
,
size
);
/* N.B. This could fail with a non-zero value (which means -EFAULT
/* N.B. This could fail with -EFAULT */
* and the non-zero value is the number of bytes not copied).
*/
memcpy_toiovec
(
msg
->
msg_iov
,
skb
->
data
,
chunk
);
memcpy_toiovec
(
msg
->
msg_iov
,
skb
->
data
,
chunk
);
copied
+=
chunk
;
copied
+=
chunk
;
size
-=
chunk
;
size
-=
chunk
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment