Commit 2fe16088 authored by Jiri Slaby (SUSE)'s avatar Jiri Slaby (SUSE) Committed by Greg Kroah-Hartman
Browse files

tty/vt: use guard()s in con_font_set/get() and con_{set,get}_unimap()

Having all the new guards, use them in the 8250_rsa code. This improves
readability, makes error handling easier, and marks locked portions of
code explicit.

The new __free()-annotated declarations are moved to the allocation points
as is preferred:
https://lore.kernel.org/all/CAHk-=wjvh_LUpa=864joG2JJXs3+viO-kLzLidR2JLyMr4MNwA@mail.gmail.com/



Except font_data in con_font_get(). The scope in there would not match
the expected lifetime. But the declaration is moved closer.

Signed-off-by: default avatar"Jiri Slaby (SUSE)" <jirislaby@kernel.org>
Link: https://lore.kernel.org/r/20250814072456.182853-15-jirislaby@kernel.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 54faf047
Loading
Loading
Loading
Loading
+38 −46
Original line number Diff line number Diff line
@@ -637,32 +637,28 @@ static struct uni_pagedict *con_unshare_unimap(struct vc_data *vc,

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;
	}
@@ -671,7 +667,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
	 * 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;
	}
@@ -680,15 +676,12 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
	 * 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;
}

@@ -787,20 +780,17 @@ int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct,
{
	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();

	scoped_guard(console_lock) {
		ect = 0;
		dict = *vc->uni_pagedict_loc;
		if (!dict)
		goto unlock;
			break;

		for (d = 0; d < UNI_DIRS; d++) {
			u16 **dir = dict->uni_pgdir[d];
@@ -823,14 +813,16 @@ int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct,
				}
			}
		}
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;
}

/*
+40 −49
Original line number Diff line number Diff line
@@ -4801,57 +4801,51 @@ void reset_palette(struct vc_data *vc)
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();
	scoped_guard(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();
			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;

@@ -4870,7 +4864,7 @@ static int con_font_set(struct vc_data *vc, const struct console_font_op *op)
	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);

@@ -4878,18 +4872,17 @@ static int con_font_set(struct vc_data *vc, const struct console_font_op *op)
	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) {
		return -EINVAL;
	if (!vc->vc_sw->con_font_set)
		return -ENOSYS;

	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 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)
@@ -4897,8 +4890,6 @@ 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;
@@ -4907,23 +4898,23 @@ static int con_font_default(struct vc_data *vc, struct console_font_op *op)
	else
		name[MAX_FONT_NAME - 1] = 0;

	console_lock();
	if (vc->vc_mode != KD_TEXT) {
		console_unlock();
	scoped_guard(console_lock) {
		if (vc->vc_mode != KD_TEXT)
			return -EINVAL;
	}
	if (vc->vc_sw->con_font_default) {
		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) {
		int ret = vc->vc_sw->con_font_default(vc, &font, s);
		if (ret)
			return ret;
	}

	op->width = font.width;
	op->height = font.height;
	}
	return rc;

	return 0;
}

int con_font_op(struct vc_data *vc, struct console_font_op *op)