Skip to content

Commit 468138d

Browse files
author
Al Viro
committed
binfmt_flat: flat_{get,put}_addr_from_rp() should be able to fail
on MMU targets EFAULT is possible here. Make both return 0 or error, passing what used to be the return value of flat_get_addr_from_rp() by reference. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
1 parent 2ea659a commit 468138d

File tree

12 files changed

+168
-81
lines changed

12 files changed

+168
-81
lines changed

arch/arm/include/asm/flat.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,31 @@
55
#ifndef __ARM_FLAT_H__
66
#define __ARM_FLAT_H__
77

8+
#include <linux/uaccess.h>
9+
810
#define flat_argvp_envp_on_stack() 1
911
#define flat_old_ram_flag(flags) (flags)
1012
#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
11-
#define flat_get_addr_from_rp(rp, relval, flags, persistent) \
12-
({ unsigned long __val; __get_user_unaligned(__val, rp); __val; })
13-
#define flat_put_addr_at_rp(rp, val, relval) __put_user_unaligned(val, rp)
13+
14+
static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
15+
u32 *addr, u32 *persistent)
16+
{
17+
#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
18+
return copy_from_user(addr, rp, 4) ? -EFAULT : 0;
19+
#else
20+
return get_user(*addr, rp);
21+
#endif
22+
}
23+
24+
static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
25+
{
26+
#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
27+
return copy_to_user(rp, &addr, 4) ? -EFAULT : 0;
28+
#else
29+
return put_user(addr, rp);
30+
#endif
31+
}
32+
1433
#define flat_get_relocate_addr(rel) (rel)
1534
#define flat_set_persistent(relval, p) 0
1635

arch/blackfin/include/asm/flat.h

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,28 @@
1414
#define flat_argvp_envp_on_stack() 0
1515
#define flat_old_ram_flag(flags) (flags)
1616

17-
extern unsigned long bfin_get_addr_from_rp (unsigned long *ptr,
18-
unsigned long relval,
19-
unsigned long flags,
20-
unsigned long *persistent);
17+
extern unsigned long bfin_get_addr_from_rp (u32 *ptr, u32 relval,
18+
u32 flags, u32 *persistent);
2119

22-
extern void bfin_put_addr_at_rp(unsigned long *ptr, unsigned long addr,
23-
unsigned long relval);
20+
extern void bfin_put_addr_at_rp(u32 *ptr, u32 addr, u32 relval);
2421

2522
/* The amount by which a relocation can exceed the program image limits
2623
without being regarded as an error. */
2724

2825
#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
2926

30-
#define flat_get_addr_from_rp(rp, relval, flags, persistent) \
31-
bfin_get_addr_from_rp(rp, relval, flags, persistent)
32-
#define flat_put_addr_at_rp(rp, val, relval) \
33-
bfin_put_addr_at_rp(rp, val, relval)
27+
static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
28+
u32 *addr, u32 *persistent)
29+
{
30+
*addr = bfin_get_addr_from_rp(rp, relval, flags, persistent);
31+
return 0;
32+
}
33+
34+
static inline int flat_put_addr_at_rp(u32 __user *rp, u32 val, u32 relval)
35+
{
36+
bfin_put_addr_at_rp(rp, val, relval);
37+
return 0;
38+
}
3439

3540
/* Convert a relocation entry into an address. */
3641
static inline unsigned long

arch/blackfin/kernel/flat.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313
#define FLAT_BFIN_RELOC_TYPE_16H_BIT 1
1414
#define FLAT_BFIN_RELOC_TYPE_32_BIT 2
1515

16-
unsigned long bfin_get_addr_from_rp(unsigned long *ptr,
17-
unsigned long relval,
18-
unsigned long flags,
19-
unsigned long *persistent)
16+
unsigned long bfin_get_addr_from_rp(u32 *ptr,
17+
u32 relval,
18+
u32 flags,
19+
u32 *persistent)
2020
{
2121
unsigned short *usptr = (unsigned short *)ptr;
2222
int type = (relval >> 26) & 7;
23-
unsigned long val;
23+
u32 val;
2424

2525
switch (type) {
2626
case FLAT_BFIN_RELOC_TYPE_16_BIT:
@@ -59,8 +59,7 @@ EXPORT_SYMBOL(bfin_get_addr_from_rp);
5959
* Insert the address ADDR into the symbol reference at RP;
6060
* RELVAL is the raw relocation-table entry from which RP is derived
6161
*/
62-
void bfin_put_addr_at_rp(unsigned long *ptr, unsigned long addr,
63-
unsigned long relval)
62+
void bfin_put_addr_at_rp(u32 *ptr, u32 addr, u32 relval)
6463
{
6564
unsigned short *usptr = (unsigned short *)ptr;
6665
int type = (relval >> 26) & 7;

arch/c6x/include/asm/flat.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
#ifndef __ASM_C6X_FLAT_H
22
#define __ASM_C6X_FLAT_H
33

4+
#include <asm/unaligned.h>
5+
46
#define flat_argvp_envp_on_stack() 0
57
#define flat_old_ram_flag(flags) (flags)
68
#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
7-
#define flat_get_addr_from_rp(rp, relval, flags, p) get_unaligned(rp)
8-
#define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val, rp)
9+
static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
10+
u32 *addr, u32 *persistent)
11+
{
12+
*addr = get_unaligned((__force u32 *)rp);
13+
return 0;
14+
}
15+
static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
16+
{
17+
put_unaligned(addr, (__force u32 *)rp);
18+
return 0;
19+
}
920
#define flat_get_relocate_addr(rel) (rel)
1021
#define flat_set_persistent(relval, p) 0
1122

arch/h8300/include/asm/flat.h

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#ifndef __H8300_FLAT_H__
66
#define __H8300_FLAT_H__
77

8+
#include <asm/unaligned.h>
9+
810
#define flat_argvp_envp_on_stack() 1
911
#define flat_old_ram_flag(flags) 1
1012
#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
@@ -18,11 +20,21 @@
1820
*/
1921

2022
#define flat_get_relocate_addr(rel) (rel & ~0x00000001)
21-
#define flat_get_addr_from_rp(rp, relval, flags, persistent) \
22-
({(void)persistent; \
23-
get_unaligned(rp) & (((flags) & FLAT_FLAG_GOTPIC) ? \
24-
0xffffffff : 0x00ffffff); })
25-
#define flat_put_addr_at_rp(rp, addr, rel) \
26-
put_unaligned(((*(char *)(rp)) << 24) | ((addr) & 0x00ffffff), (rp))
23+
static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
24+
u32 *addr, u32 *persistent)
25+
{
26+
u32 val = get_unaligned((__force u32 *)rp);
27+
if (!(flags & FLAT_FLAG_GOTPIC)
28+
val &= 0x00ffffff;
29+
*addr = val;
30+
return 0;
31+
}
32+
33+
static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
34+
{
35+
u32 *p = (__force u32 *)rp;
36+
put_unaligned((addr & 0x00ffffff) | (*(char *)p << 24), p);
37+
return 0;
38+
}
2739

2840
#endif /* __H8300_FLAT_H__ */

arch/m32r/include/asm/flat.h

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,6 @@
1717
#define flat_set_persistent(relval, p) 0
1818
#define flat_reloc_valid(reloc, size) \
1919
(((reloc) - textlen_for_m32r_lo16_data) <= (size))
20-
#define flat_get_addr_from_rp(rp, relval, flags, persistent) \
21-
m32r_flat_get_addr_from_rp(rp, relval, (text_len) )
22-
23-
#define flat_put_addr_at_rp(rp, addr, relval) \
24-
m32r_flat_put_addr_at_rp(rp, addr, relval)
2520

2621
/* Convert a relocation entry into an address. */
2722
static inline unsigned long
@@ -57,9 +52,9 @@ flat_get_relocate_addr (unsigned long relval)
5752

5853
static unsigned long textlen_for_m32r_lo16_data = 0;
5954

60-
static inline unsigned long m32r_flat_get_addr_from_rp (unsigned long *rp,
61-
unsigned long relval,
62-
unsigned long textlen)
55+
static inline unsigned long m32r_flat_get_addr_from_rp (u32 *rp,
56+
u32 relval,
57+
u32 textlen)
6358
{
6459
unsigned int reloc = flat_m32r_get_reloc_type (relval);
6560
textlen_for_m32r_lo16_data = 0;
@@ -100,9 +95,7 @@ static inline unsigned long m32r_flat_get_addr_from_rp (unsigned long *rp,
10095
return ~0; /* bogus value */
10196
}
10297

103-
static inline void m32r_flat_put_addr_at_rp (unsigned long *rp,
104-
unsigned long addr,
105-
unsigned long relval)
98+
static inline void flat_put_addr_at_rp(u32 *rp, u32 addr, u32 relval)
10699
{
107100
unsigned int reloc = flat_m32r_get_reloc_type (relval);
108101
if (reloc & 0xf0) {
@@ -142,4 +135,8 @@ static inline void m32r_flat_put_addr_at_rp (unsigned long *rp,
142135
}
143136
}
144137

138+
// kludge - text_len is a local variable in the only user.
139+
#define flat_get_addr_from_rp(rp, relval, flags, addr, persistent) \
140+
(m32r_flat_get_addr_from_rp(rp, relval, text_len), 0)
141+
145142
#endif /* __ASM_M32R_FLAT_H */

arch/m68k/include/asm/flat.h

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,29 @@
55
#ifndef __M68KNOMMU_FLAT_H__
66
#define __M68KNOMMU_FLAT_H__
77

8+
#include <linux/uaccess.h>
9+
810
#define flat_argvp_envp_on_stack() 1
911
#define flat_old_ram_flag(flags) (flags)
1012
#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
11-
#define flat_get_addr_from_rp(rp, relval, flags, p) \
12-
({ unsigned long __val; __get_user_unaligned(__val, rp); __val; })
13-
#define flat_put_addr_at_rp(rp, val, relval) __put_user_unaligned(val, rp)
13+
static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
14+
u32 *addr, u32 *persistent)
15+
{
16+
#ifdef CONFIG_CPU_HAS_NO_UNALIGNED
17+
return copy_from_user(addr, rp, 4) ? -EFAULT : 0;
18+
#else
19+
return get_user(*addr, rp);
20+
#endif
21+
}
22+
23+
static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
24+
{
25+
#ifdef CONFIG_CPU_HAS_NO_UNALIGNED
26+
return copy_to_user(rp, &addr, 4) ? -EFAULT : 0;
27+
#else
28+
return put_user(addr, rp);
29+
#endif
30+
}
1431
#define flat_get_relocate_addr(rel) (rel)
1532

1633
static inline int flat_set_persistent(unsigned long relval,

arch/microblaze/include/asm/flat.h

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,29 +32,27 @@
3232
* reference
3333
*/
3434

35-
static inline unsigned long
36-
flat_get_addr_from_rp(unsigned long *rp, unsigned long relval,
37-
unsigned long flags, unsigned long *persistent)
35+
static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
36+
u32 *addr, u32 *persistent)
3837
{
39-
unsigned long addr;
40-
(void)flags;
38+
u32 *p = (__force u32 *)rp;
4139

4240
/* Is it a split 64/32 reference? */
4341
if (relval & 0x80000000) {
4442
/* Grab the two halves of the reference */
45-
unsigned long val_hi, val_lo;
43+
u32 val_hi, val_lo;
4644

47-
val_hi = get_unaligned(rp);
48-
val_lo = get_unaligned(rp+1);
45+
val_hi = get_unaligned(p);
46+
val_lo = get_unaligned(p+1);
4947

5048
/* Crack the address out */
51-
addr = ((val_hi & 0xffff) << 16) + (val_lo & 0xffff);
49+
*addr = ((val_hi & 0xffff) << 16) + (val_lo & 0xffff);
5250
} else {
5351
/* Get the address straight out */
54-
addr = get_unaligned(rp);
52+
*addr = get_unaligned(p);
5553
}
5654

57-
return addr;
55+
return 0;
5856
}
5957

6058
/*
@@ -63,25 +61,27 @@ flat_get_addr_from_rp(unsigned long *rp, unsigned long relval,
6361
*/
6462

6563
static inline void
66-
flat_put_addr_at_rp(unsigned long *rp, unsigned long addr, unsigned long relval)
64+
flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 relval)
6765
{
66+
u32 *p = (__force u32 *)rp;
6867
/* Is this a split 64/32 reloc? */
6968
if (relval & 0x80000000) {
7069
/* Get the two "halves" */
71-
unsigned long val_hi = get_unaligned(rp);
72-
unsigned long val_lo = get_unaligned(rp + 1);
70+
unsigned long val_hi = get_unaligned(p);
71+
unsigned long val_lo = get_unaligned(p + 1);
7372

7473
/* insert the address */
7574
val_hi = (val_hi & 0xffff0000) | addr >> 16;
7675
val_lo = (val_lo & 0xffff0000) | (addr & 0xffff);
7776

7877
/* store the two halves back into memory */
79-
put_unaligned(val_hi, rp);
80-
put_unaligned(val_lo, rp+1);
78+
put_unaligned(val_hi, p);
79+
put_unaligned(val_lo, p+1);
8180
} else {
8281
/* Put it straight in, no messing around */
83-
put_unaligned(addr, rp);
82+
put_unaligned(addr, p);
8483
}
84+
return 0;
8585
}
8686

8787
#define flat_get_relocate_addr(rel) (rel & 0x7fffffff)

arch/sh/include/asm/flat.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,22 @@
1212
#ifndef __ASM_SH_FLAT_H
1313
#define __ASM_SH_FLAT_H
1414

15+
#include <asm/unaligned.h>
16+
1517
#define flat_argvp_envp_on_stack() 0
1618
#define flat_old_ram_flag(flags) (flags)
1719
#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
18-
#define flat_get_addr_from_rp(rp, relval, flags, p) get_unaligned(rp)
19-
#define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp)
20+
static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
21+
u32 *addr, u32 *persistent)
22+
{
23+
*addr = get_unaligned((__force u32 *)rp);
24+
return 0;
25+
}
26+
static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
27+
{
28+
put_unaligned(addr, (__force u32 *)rp);
29+
return 0;
30+
}
2031
#define flat_get_relocate_addr(rel) (rel)
2132
#define flat_set_persistent(relval, p) ({ (void)p; 0; })
2233

arch/xtensa/include/asm/flat.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
11
#ifndef __ASM_XTENSA_FLAT_H
22
#define __ASM_XTENSA_FLAT_H
33

4+
#include <asm/unaligned.h>
5+
46
#define flat_argvp_envp_on_stack() 0
57
#define flat_old_ram_flag(flags) (flags)
68
#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
7-
#define flat_get_addr_from_rp(rp, relval, flags, p) get_unaligned(rp)
8-
#define flat_put_addr_at_rp(rp, val, relval ) put_unaligned(val, rp)
9+
static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags,
10+
u32 *addr, u32 *persistent)
11+
{
12+
*addr = get_unaligned((__force u32 *)rp);
13+
return 0;
14+
}
15+
static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel)
16+
{
17+
put_unaligned(addr, (__force u32 *)rp);
18+
return 0;
19+
}
920
#define flat_get_relocate_addr(rel) (rel)
1021
#define flat_set_persistent(relval, p) 0
1122

0 commit comments

Comments
 (0)