| .. | .. | 
|---|
 | 1 | +// SPDX-License-Identifier: GPL-2.0-or-later  | 
|---|
| 1 | 2 |  /* | 
|---|
| 2 | 3 |   * Copyright (C) 2017 Joe Lawrence <joe.lawrence@redhat.com> | 
|---|
| 3 |  | - *  | 
|---|
| 4 |  | - * This program is free software; you can redistribute it and/or  | 
|---|
| 5 |  | - * modify it under the terms of the GNU General Public License  | 
|---|
| 6 |  | - * as published by the Free Software Foundation; either version 2  | 
|---|
| 7 |  | - * of the License, or (at your option) any later version.  | 
|---|
| 8 |  | - *  | 
|---|
| 9 |  | - * This program is distributed in the hope that it will be useful,  | 
|---|
| 10 |  | - * but WITHOUT ANY WARRANTY; without even the implied warranty of  | 
|---|
| 11 |  | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  | 
|---|
| 12 |  | - * GNU General Public License for more details.  | 
|---|
| 13 |  | - *  | 
|---|
| 14 |  | - * You should have received a copy of the GNU General Public License  | 
|---|
| 15 |  | - * along with this program; if not, see <http://www.gnu.org/licenses/>.  | 
|---|
| 16 | 4 |   */ | 
|---|
| 17 | 5 |   | 
|---|
| 18 | 6 |  /* | 
|---|
| .. | .. | 
|---|
| 64 | 52 |   */ | 
|---|
| 65 | 53 |  static int shadow_leak_ctor(void *obj, void *shadow_data, void *ctor_data) | 
|---|
| 66 | 54 |  { | 
|---|
| 67 |  | -	void **shadow_leak = shadow_data;  | 
|---|
| 68 |  | -	void *leak = ctor_data;  | 
|---|
 | 55 | +	int **shadow_leak = shadow_data;  | 
|---|
 | 56 | +	int **leak = ctor_data;  | 
|---|
| 69 | 57 |   | 
|---|
| 70 |  | -	*shadow_leak = leak;  | 
|---|
 | 58 | +	if (!ctor_data)  | 
|---|
 | 59 | +		return -EINVAL;  | 
|---|
 | 60 | +  | 
|---|
 | 61 | +	*shadow_leak = *leak;  | 
|---|
| 71 | 62 |  	return 0; | 
|---|
| 72 | 63 |  } | 
|---|
| 73 | 64 |   | 
|---|
| 74 |  | -struct dummy *livepatch_fix1_dummy_alloc(void)  | 
|---|
 | 65 | +static struct dummy *livepatch_fix1_dummy_alloc(void)  | 
|---|
| 75 | 66 |  { | 
|---|
| 76 | 67 |  	struct dummy *d; | 
|---|
| 77 |  | -	void *leak;  | 
|---|
 | 68 | +	int *leak;  | 
|---|
 | 69 | +	int **shadow_leak;  | 
|---|
| 78 | 70 |   | 
|---|
| 79 | 71 |  	d = kzalloc(sizeof(*d), GFP_KERNEL); | 
|---|
| 80 | 72 |  	if (!d) | 
|---|
| .. | .. | 
|---|
| 88 | 80 |  	 * variable.  A patched dummy_free routine can later fetch this | 
|---|
| 89 | 81 |  	 * pointer to handle resource release. | 
|---|
| 90 | 82 |  	 */ | 
|---|
| 91 |  | -	leak = kzalloc(sizeof(int), GFP_KERNEL);  | 
|---|
| 92 |  | -	if (!leak) {  | 
|---|
| 93 |  | -		kfree(d);  | 
|---|
| 94 |  | -		return NULL;  | 
|---|
| 95 |  | -	}  | 
|---|
 | 83 | +	leak = kzalloc(sizeof(*leak), GFP_KERNEL);  | 
|---|
 | 84 | +	if (!leak)  | 
|---|
 | 85 | +		goto err_leak;  | 
|---|
| 96 | 86 |   | 
|---|
| 97 |  | -	klp_shadow_alloc(d, SV_LEAK, sizeof(leak), GFP_KERNEL,  | 
|---|
| 98 |  | -			 shadow_leak_ctor, leak);  | 
|---|
 | 87 | +	shadow_leak = klp_shadow_alloc(d, SV_LEAK, sizeof(leak), GFP_KERNEL,  | 
|---|
 | 88 | +				       shadow_leak_ctor, &leak);  | 
|---|
 | 89 | +	if (!shadow_leak) {  | 
|---|
 | 90 | +		pr_err("%s: failed to allocate shadow variable for the leaking pointer: dummy @ %p, leak @ %p\n",  | 
|---|
 | 91 | +		       __func__, d, leak);  | 
|---|
 | 92 | +		goto err_shadow;  | 
|---|
 | 93 | +	}  | 
|---|
| 99 | 94 |   | 
|---|
| 100 | 95 |  	pr_info("%s: dummy @ %p, expires @ %lx\n", | 
|---|
| 101 | 96 |  		__func__, d, d->jiffies_expire); | 
|---|
| 102 | 97 |   | 
|---|
| 103 | 98 |  	return d; | 
|---|
 | 99 | +  | 
|---|
 | 100 | +err_shadow:  | 
|---|
 | 101 | +	kfree(leak);  | 
|---|
 | 102 | +err_leak:  | 
|---|
 | 103 | +	kfree(d);  | 
|---|
 | 104 | +	return NULL;  | 
|---|
| 104 | 105 |  } | 
|---|
| 105 | 106 |   | 
|---|
| 106 | 107 |  static void livepatch_fix1_dummy_leak_dtor(void *obj, void *shadow_data) | 
|---|
| 107 | 108 |  { | 
|---|
| 108 | 109 |  	void *d = obj; | 
|---|
| 109 |  | -	void **shadow_leak = shadow_data;  | 
|---|
 | 110 | +	int **shadow_leak = shadow_data;  | 
|---|
| 110 | 111 |   | 
|---|
| 111 | 112 |  	kfree(*shadow_leak); | 
|---|
| 112 | 113 |  	pr_info("%s: dummy @ %p, prevented leak @ %p\n", | 
|---|
| 113 | 114 |  			 __func__, d, *shadow_leak); | 
|---|
| 114 | 115 |  } | 
|---|
| 115 | 116 |   | 
|---|
| 116 |  | -void livepatch_fix1_dummy_free(struct dummy *d)  | 
|---|
 | 117 | +static void livepatch_fix1_dummy_free(struct dummy *d)  | 
|---|
| 117 | 118 |  { | 
|---|
| 118 |  | -	void **shadow_leak;  | 
|---|
 | 119 | +	int **shadow_leak;  | 
|---|
| 119 | 120 |   | 
|---|
| 120 | 121 |  	/* | 
|---|
| 121 | 122 |  	 * Patch: fetch the saved SV_LEAK shadow variable, detach and | 
|---|
| .. | .. | 
|---|
| 157 | 158 |   | 
|---|
| 158 | 159 |  static int livepatch_shadow_fix1_init(void) | 
|---|
| 159 | 160 |  { | 
|---|
| 160 |  | -	int ret;  | 
|---|
| 161 |  | -  | 
|---|
| 162 |  | -	ret = klp_register_patch(&patch);  | 
|---|
| 163 |  | -	if (ret)  | 
|---|
| 164 |  | -		return ret;  | 
|---|
| 165 |  | -	ret = klp_enable_patch(&patch);  | 
|---|
| 166 |  | -	if (ret) {  | 
|---|
| 167 |  | -		WARN_ON(klp_unregister_patch(&patch));  | 
|---|
| 168 |  | -		return ret;  | 
|---|
| 169 |  | -	}  | 
|---|
| 170 |  | -	return 0;  | 
|---|
 | 161 | +	return klp_enable_patch(&patch);  | 
|---|
| 171 | 162 |  } | 
|---|
| 172 | 163 |   | 
|---|
| 173 | 164 |  static void livepatch_shadow_fix1_exit(void) | 
|---|
| 174 | 165 |  { | 
|---|
| 175 | 166 |  	/* Cleanup any existing SV_LEAK shadow variables */ | 
|---|
| 176 | 167 |  	klp_shadow_free_all(SV_LEAK, livepatch_fix1_dummy_leak_dtor); | 
|---|
| 177 |  | -  | 
|---|
| 178 |  | -	WARN_ON(klp_unregister_patch(&patch));  | 
|---|
| 179 | 168 |  } | 
|---|
| 180 | 169 |   | 
|---|
| 181 | 170 |  module_init(livepatch_shadow_fix1_init); | 
|---|