Skip to content

Commit e2cdf1b

Browse files
PettitWesleyedsiper
authored andcommitted
aws: protect credential providers with pthread_mutex
Signed-off-by: Wesley Pettit <[email protected]>
1 parent 54b8a7c commit e2cdf1b

File tree

6 files changed

+53
-22
lines changed

6 files changed

+53
-22
lines changed

include/fluent-bit/flb_aws_credentials.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,13 @@ struct flb_aws_provider_vtable {
118118
*/
119119
struct flb_aws_provider {
120120
/*
121-
* Fluent Bit is single-threaded but asynchonous. Co-routines are paused
122-
* and resumed during blocking IO calls.
123-
*
121+
* Fluent Bit now has multi-threads/workers, need to a mutex to protect cred provider.
124122
* When a refresh is needed, only one co-routine should refresh.
123+
* When one thread refreshes, the cached creds are freed and reset, there could be a double
124+
* free without a lock.
125+
* We use trylock to prevent deadlock.
125126
*/
126-
int locked;
127+
pthread_mutex_t lock;
127128

128129
struct flb_aws_provider_vtable *provider_vtable;
129130

src/aws/flb_aws_credentials.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,8 @@ static struct flb_aws_provider *standard_chain_create(struct flb_config
537537
return NULL;
538538
}
539539

540+
pthread_mutex_init(&provider->lock, NULL);
541+
540542
implementation = flb_calloc(1, sizeof(struct flb_aws_provider_chain));
541543

542544
if (!implementation) {
@@ -768,6 +770,8 @@ void flb_aws_provider_destroy(struct flb_aws_provider *provider)
768770
provider->provider_vtable->destroy(provider);
769771
}
770772

773+
pthread_mutex_destroy(&provider->lock);
774+
771775
/* free managed dependencies */
772776
if (provider->base_aws_provider) {
773777
flb_aws_provider_destroy(provider->base_aws_provider);
@@ -834,27 +838,25 @@ time_t flb_aws_cred_expiration(const char *timestamp)
834838
}
835839

836840
/*
837-
* Fluent Bit is single-threaded but asynchonous. Only one co-routine will
838-
* be running at a time, and they only pause/resume for IO.
839-
*
840-
* Thus, while synchronization is needed (to prevent multiple co-routines
841-
* from duplicating effort and performing the same work), it can be obtained
842-
* using a simple integer flag on the provider.
841+
* Fluent Bit is now multi-threaded and asynchonous with coros.
842+
* The trylock prevents deadlock, and protects the provider
843+
* when a cred refresh happens. The refresh frees and
844+
* sets the shared cred cache, a double free could occur
845+
* if two threads do it at the same exact time.
843846
*/
844847

845848
/* Like a traditional try lock- it does not block if the lock is not obtained */
846849
int try_lock_provider(struct flb_aws_provider *provider)
847850
{
848-
if (provider->locked == FLB_TRUE) {
851+
int ret = 0;
852+
ret = pthread_mutex_trylock(&provider->lock);
853+
if (ret != 0) {
849854
return FLB_FALSE;
850855
}
851-
provider->locked = FLB_TRUE;
852856
return FLB_TRUE;
853857
}
854858

855859
void unlock_provider(struct flb_aws_provider *provider)
856860
{
857-
if (provider->locked == FLB_TRUE) {
858-
provider->locked = FLB_FALSE;
859-
}
861+
pthread_mutex_unlock(&provider->lock);
860862
}

src/aws/flb_aws_credentials_ec2.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ struct flb_aws_provider *flb_ec2_provider_create(struct flb_config *config,
229229
return NULL;
230230
}
231231

232+
pthread_mutex_init(&provider->lock, NULL);
233+
232234
implementation = flb_calloc(1, sizeof(struct flb_aws_provider_ec2));
233235

234236
if (!implementation) {

src/aws/flb_aws_credentials_http.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,8 @@ struct flb_aws_provider *flb_http_provider_create(struct flb_config *config,
250250
return NULL;
251251
}
252252

253+
pthread_mutex_init(&provider->lock, NULL);
254+
253255
implementation = flb_calloc(1, sizeof(struct flb_aws_provider_http));
254256

255257
if (!implementation) {

src/aws/flb_aws_credentials_profile.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,16 @@ struct flb_aws_credentials *get_credentials_fn_profile(struct flb_aws_provider
103103
time(NULL) >= implementation->next_refresh)) {
104104
AWS_CREDS_DEBUG("Retrieving credentials for AWS Profile %s",
105105
implementation->profile);
106-
ret = refresh_credentials(implementation, FLB_FALSE);
107-
if (ret < 0) {
108-
AWS_CREDS_ERROR("Failed to retrieve credentials for AWS Profile %s",
109-
implementation->profile);
106+
if (try_lock_provider(provider) == FLB_TRUE) {
107+
ret = refresh_credentials(implementation, FLB_FALSE);
108+
unlock_provider(provider);
109+
if (ret < 0) {
110+
AWS_CREDS_ERROR("Failed to retrieve credentials for AWS Profile %s",
111+
implementation->profile);
112+
return NULL;
113+
}
114+
} else {
115+
AWS_CREDS_WARN("Another thread is refreshing credentials, will retry");
110116
return NULL;
111117
}
112118
}
@@ -152,15 +158,27 @@ struct flb_aws_credentials *get_credentials_fn_profile(struct flb_aws_provider
152158
int refresh_fn_profile(struct flb_aws_provider *provider)
153159
{
154160
struct flb_aws_provider_profile *implementation = provider->implementation;
161+
int ret = -1;
155162
AWS_CREDS_DEBUG("Refresh called on the profile provider");
156-
return refresh_credentials(implementation, FLB_FALSE);
163+
if (try_lock_provider(provider) == FLB_TRUE) {
164+
ret = refresh_credentials(implementation, FLB_FALSE);
165+
unlock_provider(provider);
166+
return ret;
167+
}
168+
return ret;
157169
}
158170

159171
int init_fn_profile(struct flb_aws_provider *provider)
160172
{
161173
struct flb_aws_provider_profile *implementation = provider->implementation;
174+
int ret = -1;
162175
AWS_CREDS_DEBUG("Init called on the profile provider");
163-
return refresh_credentials(implementation, FLB_TRUE);
176+
if (try_lock_provider(provider) == FLB_TRUE) {
177+
ret = refresh_credentials(implementation, FLB_TRUE);
178+
unlock_provider(provider);
179+
return ret;
180+
}
181+
return ret;
164182
}
165183

166184
/*
@@ -234,6 +252,8 @@ struct flb_aws_provider *flb_profile_provider_create(char* profile)
234252
goto error;
235253
}
236254

255+
pthread_mutex_init(&provider->lock, NULL);
256+
237257
implementation = flb_calloc(1,
238258
sizeof(
239259
struct flb_aws_provider_profile));

src/aws/flb_aws_credentials_sts.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,8 @@ struct flb_aws_provider *flb_sts_provider_create(struct flb_config *config,
308308
return NULL;
309309
}
310310

311+
pthread_mutex_init(&provider->lock, NULL);
312+
311313
implementation = flb_calloc(1, sizeof(struct flb_aws_provider_sts));
312314
if (!implementation) {
313315
goto error;
@@ -578,7 +580,9 @@ struct flb_aws_provider *flb_eks_provider_create(struct flb_config *config,
578580
flb_errno();
579581
return NULL;
580582
}
581-
583+
584+
pthread_mutex_init(&provider->lock, NULL);
585+
582586
implementation = flb_calloc(1, sizeof(struct flb_aws_provider_eks));
583587

584588
if (!implementation) {

0 commit comments

Comments
 (0)