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

ceph: ensure auth ops are defined before use

In the create_authorizer method for both the mds and osd clients,
the auth_client->ops pointer is blindly dereferenced. There is no
obvious guarantee that this pointer has been assigned. And
furthermore, even if the ops pointer is non-null there is definitely
no guarantee that the create_authorizer or destroy_authorizer
methods are defined.

Add checks in both routines to make sure they are defined (non-null)
before use. Add similar checks in a few other spots in these files
while we're at it.

Signed-off-by: Alex Elder <elder@inktank.com>
Reviewed-by: Sage Weil <sage@inktank.com>

authored by

Alex Elder and committed by
Alex Elder
a255651d 74f1869f

+16 -13
+6 -8
fs/ceph/mds_client.c
··· 3406 3406 int ret = 0; 3407 3407 3408 3408 if (force_new && auth->authorizer) { 3409 - ac->ops->destroy_authorizer(ac, auth->authorizer); 3409 + if (ac->ops && ac->ops->destroy_authorizer) 3410 + ac->ops->destroy_authorizer(ac, auth->authorizer); 3410 3411 auth->authorizer = NULL; 3411 3412 } 3412 - if (auth->authorizer == NULL) { 3413 - if (ac->ops->create_authorizer) { 3414 - ret = ac->ops->create_authorizer(ac, 3415 - CEPH_ENTITY_TYPE_MDS, auth); 3416 - if (ret) 3417 - return ret; 3418 - } 3413 + if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) { 3414 + ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_MDS, auth); 3415 + if (ret) 3416 + return ret; 3419 3417 } 3420 3418 3421 3419 *proto = ac->protocol;
+10 -5
net/ceph/osd_client.c
··· 664 664 { 665 665 dout("put_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref), 666 666 atomic_read(&osd->o_ref) - 1); 667 - if (atomic_dec_and_test(&osd->o_ref)) { 667 + if (atomic_dec_and_test(&osd->o_ref) && osd->o_auth.authorizer) { 668 668 struct ceph_auth_client *ac = osd->o_osdc->client->monc.auth; 669 669 670 - if (osd->o_auth.authorizer) 670 + if (ac->ops && ac->ops->destroy_authorizer) 671 671 ac->ops->destroy_authorizer(ac, osd->o_auth.authorizer); 672 672 kfree(osd); 673 673 } ··· 2119 2119 int ret = 0; 2120 2120 2121 2121 if (force_new && auth->authorizer) { 2122 - ac->ops->destroy_authorizer(ac, auth->authorizer); 2122 + if (ac->ops && ac->ops->destroy_authorizer) 2123 + ac->ops->destroy_authorizer(ac, auth->authorizer); 2123 2124 auth->authorizer = NULL; 2124 2125 } 2125 - if (auth->authorizer == NULL) { 2126 + if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) { 2126 2127 ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_OSD, auth); 2127 2128 if (ret) 2128 2129 return ret; ··· 2145 2144 struct ceph_osd_client *osdc = o->o_osdc; 2146 2145 struct ceph_auth_client *ac = osdc->client->monc.auth; 2147 2146 2147 + /* 2148 + * XXX If ac->ops or ac->ops->verify_authorizer_reply is null, 2149 + * XXX which do we do: succeed or fail? 2150 + */ 2148 2151 return ac->ops->verify_authorizer_reply(ac, o->o_auth.authorizer, len); 2149 2152 } 2150 2153 ··· 2158 2153 struct ceph_osd_client *osdc = o->o_osdc; 2159 2154 struct ceph_auth_client *ac = osdc->client->monc.auth; 2160 2155 2161 - if (ac->ops->invalidate_authorizer) 2156 + if (ac->ops && ac->ops->invalidate_authorizer) 2162 2157 ac->ops->invalidate_authorizer(ac, CEPH_ENTITY_TYPE_OSD); 2163 2158 2164 2159 return ceph_monc_validate_auth(&osdc->client->monc);