int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
{
- int err = 0, err1;
struct uni_pagedict *dict;
- struct unipair *unilist, *plist;
+ struct unipair *plist;
+ int err = 0;
if (!ct)
return 0;
- unilist = vmemdup_array_user(list, ct, sizeof(*unilist));
+ struct unipair *unilist __free(kvfree) = vmemdup_array_user(list, ct, sizeof(*unilist));
if (IS_ERR(unilist))
return PTR_ERR(unilist);
- console_lock();
+ guard(console_lock)();
/* Save original vc_unipagdir_loc in case we allocate a new one */
dict = *vc->uni_pagedict_loc;
- if (!dict) {
- err = -EINVAL;
- goto out_unlock;
- }
+ if (!dict)
+ return -EINVAL;
if (dict->refcount > 1) {
dict = con_unshare_unimap(vc, dict);
- if (IS_ERR(dict)) {
- err = PTR_ERR(dict);
- goto out_unlock;
- }
+ if (IS_ERR(dict))
+ return PTR_ERR(dict);
} else if (dict == dflt) {
dflt = NULL;
}
* Insert user specified unicode pairs into new table.
*/
for (plist = unilist; ct; ct--, plist++) {
- err1 = con_insert_unipair(dict, plist->unicode, plist->fontpos);
+ int err1 = con_insert_unipair(dict, plist->unicode, plist->fontpos);
if (err1)
err = err1;
}
* Merge with fontmaps of any other virtual consoles.
*/
if (con_unify_unimap(vc, dict))
- goto out_unlock;
+ return err;
for (enum translation_map m = FIRST_MAP; m <= LAST_MAP; m++)
set_inverse_transl(vc, dict, m);
set_inverse_trans_unicode(dict);
-out_unlock:
- console_unlock();
- kvfree(unilist);
return err;
}
{
ushort ect;
struct uni_pagedict *dict;
- struct unipair *unilist;
unsigned int d, r, g;
- int ret = 0;
- unilist = kvmalloc_array(ct, sizeof(*unilist), GFP_KERNEL);
+ struct unipair *unilist __free(kvfree) = kvmalloc_array(ct, sizeof(*unilist), GFP_KERNEL);
if (!unilist)
return -ENOMEM;
- console_lock();
-
- ect = 0;
- dict = *vc->uni_pagedict_loc;
- if (!dict)
- goto unlock;
-
- for (d = 0; d < UNI_DIRS; d++) {
- u16 **dir = dict->uni_pgdir[d];
- if (!dir)
- continue;
+ scoped_guard(console_lock) {
+ ect = 0;
+ dict = *vc->uni_pagedict_loc;
+ if (!dict)
+ break;
- for (r = 0; r < UNI_DIR_ROWS; r++) {
- u16 *row = dir[r];
- if (!row)
+ for (d = 0; d < UNI_DIRS; d++) {
+ u16 **dir = dict->uni_pgdir[d];
+ if (!dir)
continue;
- for (g = 0; g < UNI_ROW_GLYPHS; g++, row++) {
- if (*row >= MAX_GLYPH)
+ for (r = 0; r < UNI_DIR_ROWS; r++) {
+ u16 *row = dir[r];
+ if (!row)
continue;
- if (ect < ct) {
- unilist[ect].unicode = UNI(d, r, g);
- unilist[ect].fontpos = *row;
+
+ for (g = 0; g < UNI_ROW_GLYPHS; g++, row++) {
+ if (*row >= MAX_GLYPH)
+ continue;
+ if (ect < ct) {
+ unilist[ect].unicode = UNI(d, r, g);
+ unilist[ect].fontpos = *row;
+ }
+ ect++;
}
- ect++;
}
}
}
-unlock:
- console_unlock();
+
if (copy_to_user(list, unilist, min(ect, ct) * sizeof(*unilist)))
- ret = -EFAULT;
+ return -EFAULT;
if (put_user(ect, uct))
- ret = -EFAULT;
- kvfree(unilist);
- return ret ? ret : (ect <= ct) ? 0 : -ENOMEM;
+ return -EFAULT;
+ if (ect > ct)
+ return -ENOMEM;
+
+ return 0;
}
/*
static int con_font_get(struct vc_data *vc, struct console_font_op *op)
{
struct console_font font;
- int rc = -EINVAL;
int c;
unsigned int vpitch = op->op == KD_FONT_OP_GET_TALL ? op->height : 32;
if (vpitch > max_font_height)
return -EINVAL;
+ void *font_data __free(kvfree) = NULL;
if (op->data) {
- font.data = kvzalloc(max_font_size, GFP_KERNEL);
+ font.data = font_data = kvzalloc(max_font_size, GFP_KERNEL);
if (!font.data)
return -ENOMEM;
} else
font.data = NULL;
- console_lock();
- if (vc->vc_mode != KD_TEXT)
- rc = -EINVAL;
- else if (vc->vc_sw->con_font_get)
- rc = vc->vc_sw->con_font_get(vc, &font, vpitch);
- else
- rc = -ENOSYS;
- console_unlock();
+ scoped_guard(console_lock) {
+ if (vc->vc_mode != KD_TEXT)
+ return -EINVAL;
+ if (!vc->vc_sw->con_font_get)
+ return -ENOSYS;
- if (rc)
- goto out;
+ int ret = vc->vc_sw->con_font_get(vc, &font, vpitch);
+ if (ret)
+ return ret;
+ }
c = (font.width+7)/8 * vpitch * font.charcount;
if (op->data && font.charcount > op->charcount)
- rc = -ENOSPC;
+ return -ENOSPC;
if (font.width > op->width || font.height > op->height)
- rc = -ENOSPC;
- if (rc)
- goto out;
+ return -ENOSPC;
op->height = font.height;
op->width = font.width;
op->charcount = font.charcount;
if (op->data && copy_to_user(op->data, font.data, c))
- rc = -EFAULT;
+ return -EFAULT;
-out:
- kvfree(font.data);
- return rc;
+ return 0;
}
static int con_font_set(struct vc_data *vc, const struct console_font_op *op)
{
struct console_font font;
- int rc = -EINVAL;
int size;
unsigned int vpitch = op->op == KD_FONT_OP_SET_TALL ? op->height : 32;
if (size > max_font_size)
return -ENOSPC;
- font.data = memdup_user(op->data, size);
+ void *font_data __free(kfree) = font.data = memdup_user(op->data, size);
if (IS_ERR(font.data))
return PTR_ERR(font.data);
font.width = op->width;
font.height = op->height;
- console_lock();
+ guard(console_lock)();
+
if (vc->vc_mode != KD_TEXT)
- rc = -EINVAL;
- else if (vc->vc_sw->con_font_set) {
- if (vc_is_sel(vc))
- clear_selection();
- rc = vc->vc_sw->con_font_set(vc, &font, vpitch, op->flags);
- } else
- rc = -ENOSYS;
- console_unlock();
- kfree(font.data);
- return rc;
+ return -EINVAL;
+ if (!vc->vc_sw->con_font_set)
+ return -ENOSYS;
+
+ if (vc_is_sel(vc))
+ clear_selection();
+
+ return vc->vc_sw->con_font_set(vc, &font, vpitch, op->flags);
}
static int con_font_default(struct vc_data *vc, struct console_font_op *op)
struct console_font font = {.width = op->width, .height = op->height};
char name[MAX_FONT_NAME];
char *s = name;
- int rc;
-
if (!op->data)
s = NULL;
else
name[MAX_FONT_NAME - 1] = 0;
- console_lock();
- if (vc->vc_mode != KD_TEXT) {
- console_unlock();
- return -EINVAL;
- }
- if (vc->vc_sw->con_font_default) {
+ scoped_guard(console_lock) {
+ if (vc->vc_mode != KD_TEXT)
+ return -EINVAL;
+ if (!vc->vc_sw->con_font_default)
+ return -ENOSYS;
+
if (vc_is_sel(vc))
clear_selection();
- rc = vc->vc_sw->con_font_default(vc, &font, s);
- } else
- rc = -ENOSYS;
- console_unlock();
- if (!rc) {
- op->width = font.width;
- op->height = font.height;
+ int ret = vc->vc_sw->con_font_default(vc, &font, s);
+ if (ret)
+ return ret;
}
- return rc;
+
+ op->width = font.width;
+ op->height = font.height;
+
+ return 0;
}
int con_font_op(struct vc_data *vc, struct console_font_op *op)