Commit e47efd84 authored by David S. Miller's avatar David S. Miller

[SPARC64]: Fix set_utsname returning with uts semaphore held.

Based upon a patch from Alexander Stohr.

This thing was also reimplementing strnchr() as well.
Signed-off-by: default avatarDavid S. Miller <davem@redhat.com>
parent 0a440cec
...@@ -137,21 +137,34 @@ asmlinkage int solaris_brk(u32 brk) ...@@ -137,21 +137,34 @@ asmlinkage int solaris_brk(u32 brk)
return sunos_brk(brk); return sunos_brk(brk);
} }
#define set_utsfield(to, from, dotchop, countfrom) { \ static int __set_utsfield(char __user *to, int to_size,
char *p; \ const char *from, int from_size,
int i, len = (countfrom) ? \ int dotchop, int countfrom)
((sizeof(to) > sizeof(from) ? \ {
sizeof(from) : sizeof(to))) : sizeof(to); \ int len = countfrom ? (to_size > from_size ?
if (copy_to_user(to, from, len)) \ from_size : to_size) : to_size;
return -EFAULT; \ int off;
if (dotchop) \
for (p=from,i=0; *p && *p != '.' && --len; p++,i++); \ if (copy_to_user(to, from, len))
else \ return -EFAULT;
i = len - 1; \
if (__put_user('\0', (char __user *)((to)+i))) \ if (dotchop) {
return -EFAULT; \ off = (strnchr(from, len, '.') - from);
} else{
off = len - 1;
}
if (__put_user('\0', to + off))
return -EFAULT;
return 0;
} }
#define set_utsfield(to, from, dotchop, countfrom) \
__set_utsfield((to), sizeof(to), \
(from), sizeof(from), \
(dotchop), (countfrom))
struct sol_uname { struct sol_uname {
char sysname[9]; char sysname[9];
char nodename[9]; char nodename[9];
...@@ -219,17 +232,20 @@ static char *serial(char *buffer) ...@@ -219,17 +232,20 @@ static char *serial(char *buffer)
asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2) asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2)
{ {
struct sol_uname __user *v = A(buf); struct sol_uname __user *v = A(buf);
int err;
switch (which) { switch (which) {
case 0: /* old uname */ case 0: /* old uname */
/* Let's cheat */ /* Let's cheat */
set_utsfield(v->sysname, "SunOS", 1, 0); err = set_utsfield(v->sysname, "SunOS", 1, 0);
down_read(&uts_sem); down_read(&uts_sem);
set_utsfield(v->nodename, system_utsname.nodename, 1, 1); err |= set_utsfield(v->nodename, system_utsname.nodename,
1, 1);
up_read(&uts_sem); up_read(&uts_sem);
set_utsfield(v->release, "2.6", 0, 0); err |= set_utsfield(v->release, "2.6", 0, 0);
set_utsfield(v->version, "Generic", 0, 0); err |= set_utsfield(v->version, "Generic", 0, 0);
set_utsfield(v->machine, machine(), 0, 0); err |= set_utsfield(v->machine, machine(), 0, 0);
return 0; return (err ? -EFAULT : 0);
case 2: /* ustat */ case 2: /* ustat */
return -ENOSYS; return -ENOSYS;
case 3: /* fusers */ case 3: /* fusers */
...@@ -242,15 +258,18 @@ asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2) ...@@ -242,15 +258,18 @@ asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2)
asmlinkage int solaris_utsname(u32 buf) asmlinkage int solaris_utsname(u32 buf)
{ {
struct sol_utsname __user *v = A(buf); struct sol_utsname __user *v = A(buf);
int err;
/* Why should we not lie a bit? */ /* Why should we not lie a bit? */
down_read(&uts_sem); down_read(&uts_sem);
set_utsfield(v->sysname, "SunOS", 0, 0); err = set_utsfield(v->sysname, "SunOS", 0, 0);
set_utsfield(v->nodename, system_utsname.nodename, 1, 1); err |= set_utsfield(v->nodename, system_utsname.nodename, 1, 1);
set_utsfield(v->release, "5.6", 0, 0); err |= set_utsfield(v->release, "5.6", 0, 0);
set_utsfield(v->version, "Generic", 0, 0); err |= set_utsfield(v->version, "Generic", 0, 0);
set_utsfield(v->machine, machine(), 0, 0); err |= set_utsfield(v->machine, machine(), 0, 0);
up_read(&uts_sem); up_read(&uts_sem);
return 0;
return (err ? -EFAULT : 0);
} }
#define SI_SYSNAME 1 /* return name of operating system */ #define SI_SYSNAME 1 /* return name of operating system */
......
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