| .. | .. | 
|---|
 | 1 | +// SPDX-License-Identifier: GPL-2.0-only  | 
|---|
| 1 | 2 |  /* Copyright (c) 2017 Facebook | 
|---|
| 2 |  | - *  | 
|---|
| 3 |  | - * This program is free software; you can redistribute it and/or  | 
|---|
| 4 |  | - * modify it under the terms of version 2 of the GNU General Public  | 
|---|
| 5 |  | - * License as published by the Free Software Foundation.  | 
|---|
| 6 | 3 |   */ | 
|---|
| 7 | 4 |  #include <linux/slab.h> | 
|---|
| 8 | 5 |  #include <linux/bpf.h> | 
|---|
| .. | .. | 
|---|
| 20 | 17 |  	if (IS_ERR(inner_map)) | 
|---|
| 21 | 18 |  		return inner_map; | 
|---|
| 22 | 19 |   | 
|---|
| 23 |  | -	/* prog_array->owner_prog_type and owner_jited  | 
|---|
| 24 |  | -	 * is a runtime binding.  Doing static check alone  | 
|---|
| 25 |  | -	 * in the verifier is not enough.  | 
|---|
| 26 |  | -	 */  | 
|---|
| 27 |  | -	if (inner_map->map_type == BPF_MAP_TYPE_PROG_ARRAY ||  | 
|---|
| 28 |  | -	    inner_map->map_type == BPF_MAP_TYPE_CGROUP_STORAGE) {  | 
|---|
| 29 |  | -		fdput(f);  | 
|---|
| 30 |  | -		return ERR_PTR(-ENOTSUPP);  | 
|---|
| 31 |  | -	}  | 
|---|
| 32 |  | -  | 
|---|
| 33 | 20 |  	/* Does not support >1 level map-in-map */ | 
|---|
| 34 | 21 |  	if (inner_map->inner_map_meta) { | 
|---|
| 35 | 22 |  		fdput(f); | 
|---|
| 36 | 23 |  		return ERR_PTR(-EINVAL); | 
|---|
 | 24 | +	}  | 
|---|
 | 25 | +  | 
|---|
 | 26 | +	if (!inner_map->ops->map_meta_equal) {  | 
|---|
 | 27 | +		fdput(f);  | 
|---|
 | 28 | +		return ERR_PTR(-ENOTSUPP);  | 
|---|
 | 29 | +	}  | 
|---|
 | 30 | +  | 
|---|
 | 31 | +	if (map_value_has_spin_lock(inner_map)) {  | 
|---|
 | 32 | +		fdput(f);  | 
|---|
 | 33 | +		return ERR_PTR(-ENOTSUPP);  | 
|---|
| 37 | 34 |  	} | 
|---|
| 38 | 35 |   | 
|---|
| 39 | 36 |  	inner_map_meta_size = sizeof(*inner_map_meta); | 
|---|
| .. | .. | 
|---|
| 52 | 49 |  	inner_map_meta->value_size = inner_map->value_size; | 
|---|
| 53 | 50 |  	inner_map_meta->map_flags = inner_map->map_flags; | 
|---|
| 54 | 51 |  	inner_map_meta->max_entries = inner_map->max_entries; | 
|---|
 | 52 | +	inner_map_meta->spin_lock_off = inner_map->spin_lock_off;  | 
|---|
| 55 | 53 |   | 
|---|
| 56 | 54 |  	/* Misc members not needed in bpf_map_meta_equal() check. */ | 
|---|
| 57 | 55 |  	inner_map_meta->ops = inner_map->ops; | 
|---|
| 58 | 56 |  	if (inner_map->ops == &array_map_ops) { | 
|---|
| 59 |  | -		inner_map_meta->unpriv_array = inner_map->unpriv_array;  | 
|---|
 | 57 | +		inner_map_meta->bypass_spec_v1 = inner_map->bypass_spec_v1;  | 
|---|
| 60 | 58 |  		container_of(inner_map_meta, struct bpf_array, map)->index_mask = | 
|---|
| 61 | 59 |  		     container_of(inner_map, struct bpf_array, map)->index_mask; | 
|---|
| 62 | 60 |  	} | 
|---|
| .. | .. | 
|---|
| 77 | 75 |  	return meta0->map_type == meta1->map_type && | 
|---|
| 78 | 76 |  		meta0->key_size == meta1->key_size && | 
|---|
| 79 | 77 |  		meta0->value_size == meta1->value_size && | 
|---|
| 80 |  | -		meta0->map_flags == meta1->map_flags &&  | 
|---|
| 81 |  | -		meta0->max_entries == meta1->max_entries;  | 
|---|
 | 78 | +		meta0->map_flags == meta1->map_flags;  | 
|---|
| 82 | 79 |  } | 
|---|
| 83 | 80 |   | 
|---|
| 84 | 81 |  void *bpf_map_fd_get_ptr(struct bpf_map *map, | 
|---|
| 85 | 82 |  			 struct file *map_file /* not used */, | 
|---|
| 86 | 83 |  			 int ufd) | 
|---|
| 87 | 84 |  { | 
|---|
| 88 |  | -	struct bpf_map *inner_map;  | 
|---|
 | 85 | +	struct bpf_map *inner_map, *inner_map_meta;  | 
|---|
| 89 | 86 |  	struct fd f; | 
|---|
| 90 | 87 |   | 
|---|
| 91 | 88 |  	f = fdget(ufd); | 
|---|
| .. | .. | 
|---|
| 93 | 90 |  	if (IS_ERR(inner_map)) | 
|---|
| 94 | 91 |  		return inner_map; | 
|---|
| 95 | 92 |   | 
|---|
| 96 |  | -	if (bpf_map_meta_equal(map->inner_map_meta, inner_map))  | 
|---|
| 97 |  | -		inner_map = bpf_map_inc(inner_map, false);  | 
|---|
 | 93 | +	inner_map_meta = map->inner_map_meta;  | 
|---|
 | 94 | +	if (inner_map_meta->ops->map_meta_equal(inner_map_meta, inner_map))  | 
|---|
 | 95 | +		bpf_map_inc(inner_map);  | 
|---|
| 98 | 96 |  	else | 
|---|
| 99 | 97 |  		inner_map = ERR_PTR(-EINVAL); | 
|---|
| 100 | 98 |   | 
|---|