Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix compat console unimap regression

Why is it that since the 2f1a2ccb9c0de632ab07193becf5f7121794f6ae console
UTF-8 fixes went into 2.6.22-rc1, the PowerMac G5 shows only inverse video
question marks for the text on tty2-6? whereas tty1 is fine, and so is x86.

No fault of that patch: by removing the old fallback behaviour, it reveals
that 32-bit setfont running on 64-bit kernels has only really worked on
the current console, the rest getting faked by that inadequate fallback.

Bring the compat do_unimap_ioctl into line with the main one: PIO_UNIMAP
and GIO_UNIMAP apply to the specified tty, not redirected to fg_console.
Use the same checks, and most particularly, remember to check access_ok:
con_set_unimap and con_get_unimap are using __get_user and __put_user.

And the compat vt_check should ask for the same capability as the main
one, CAP_SYS_TTY_CONFIG rather than CAP_SYS_ADMIN. Added in vt_ioctl's
vc_cons_allocated check for safety, though failure may well be impossible.

Signed-off-by: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Hugh Dickins and committed by
Linus Torvalds
f4d43bd5 1ea09758

+25 -8
+25 -8
fs/compat_ioctl.c
··· 1194 1194 { 1195 1195 struct tty_struct *tty; 1196 1196 struct inode *inode = file->f_path.dentry->d_inode; 1197 + struct vc_data *vc; 1197 1198 1198 1199 if (file->f_op->ioctl != tty_ioctl) 1199 1200 return -EINVAL; ··· 1205 1204 1206 1205 if (tty->driver->ioctl != vt_ioctl) 1207 1206 return -EINVAL; 1208 - 1207 + 1208 + vc = (struct vc_data *)tty->driver_data; 1209 + if (!vc_cons_allocated(vc->vc_num)) /* impossible? */ 1210 + return -ENOIOCTLCMD; 1211 + 1209 1212 /* 1210 1213 * To have permissions to do most of the vt ioctls, we either have 1211 - * to be the owner of the tty, or super-user. 1214 + * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. 1212 1215 */ 1213 - if (current->signal->tty == tty || capable(CAP_SYS_ADMIN)) 1216 + if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) 1214 1217 return 1; 1215 1218 return 0; 1216 1219 } ··· 1315 1310 struct unimapdesc32 tmp; 1316 1311 struct unimapdesc32 __user *user_ud = compat_ptr(arg); 1317 1312 int perm = vt_check(file); 1318 - 1319 - if (perm < 0) return perm; 1313 + struct vc_data *vc; 1314 + 1315 + if (perm < 0) 1316 + return perm; 1320 1317 if (copy_from_user(&tmp, user_ud, sizeof tmp)) 1321 1318 return -EFAULT; 1319 + if (tmp.entries) 1320 + if (!access_ok(VERIFY_WRITE, compat_ptr(tmp.entries), 1321 + tmp.entry_ct*sizeof(struct unipair))) 1322 + return -EFAULT; 1323 + vc = ((struct tty_struct *)file->private_data)->driver_data; 1322 1324 switch (cmd) { 1323 1325 case PIO_UNIMAP: 1324 - if (!perm) return -EPERM; 1325 - return con_set_unimap(vc_cons[fg_console].d, tmp.entry_ct, compat_ptr(tmp.entries)); 1326 + if (!perm) 1327 + return -EPERM; 1328 + return con_set_unimap(vc, tmp.entry_ct, 1329 + compat_ptr(tmp.entries)); 1326 1330 case GIO_UNIMAP: 1327 - return con_get_unimap(vc_cons[fg_console].d, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries)); 1331 + if (!perm && fg_console != vc->vc_num) 1332 + return -EPERM; 1333 + return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), 1334 + compat_ptr(tmp.entries)); 1328 1335 } 1329 1336 return 0; 1330 1337 }